概述
零複製(英語:zero-copy;也叫做零拷貝)技術是指計算機執行操作時,cpu
不需要先將數據從某處內存複製到另外一個特定區域。這種技術通常通過網絡傳輸文件時節省CPU
週期和帶寬。
傳統IO傳輸模型
傳統IO分析
在Java當中IO存在這三個對象,一個是user space
用戶空間,一個是kernel space
內核空間,還有一個是hardware
磁盤對象
- 當
jvm
發起了一次讀取事件時,首先會通過內核空間對磁盤進行一次DAM的IO操作,將磁盤中的數據寫入到內核空間當中。 - 再將內核空間中的數據進行一次拷貝,將數據拷貝到用戶空間當中
- 當
jvm
發起一次寫入事件時,先將用戶空間中的數據拷貝到內核空間中 - 再通過內核空間將數據寫入到磁盤中
這種拷貝我們進行了四次拷貝
和四次上下文切換
,這種拷貝和上下文切換極大的消耗時間和性能
網絡IO改進版本
其實這種模型他也是一種零拷貝,但是它在內核當中多做了一步拷貝過程,將內核空間中的數據拷貝到了socket buffer
當中,這是這個模型的一個大缺陷。
它總共進行了兩次上下文的切換
,和三次拷貝過程
真正的零拷貝
- 在
JVM
發起讀取文件請求時,將文件操作完全交給了系統內核來操作 - 通過
DMA
拷貝將數據讀取到內核空間當中,再將內核當中的數據頭信息(比如:文件名稱,文件長度等信息拷貝到socket Buffer中 當然這個過程時間我們可以忽略不記)再將kemel buffer
中的數據通過文件引擎,配合socket buffer
中的信息一起寫入到文件磁盤當中。 - 當然這種拷貝需要系統支持
scatter-and-gather
Java NIO中實現零拷貝的幾種方式
DirectByteBuffer
在調用ByteBuffer.allocateDirect()
方法獲得。JVM將使用malloc()
方法在堆內存之外分配內存空間。因爲它不是由JVM
管理,所以你的內存空間是頁面對其的,不受GC影響 ,這使得它成爲處理本地代碼的完美選擇。然而你需要像C程序員一樣,自己管理內存。
MappedByteBuffer
零拷貝是操作系統底層的一種實現,我們在網絡編程中,利用操作系統這一特性,可以大大提高數據傳輸的效率。這也是目前網絡編程框架中都會採用的方式,理解好零拷貝,有助於我們進一步學習Netty等網絡通信框架的底層原理。