在學習netty的過程當中,發現Netty對緩存作了不少優化,其中零拷貝一直令我迷惑,因此在網上找了一些博客進行學習,並做此總結css
零複製(英語:Zero-copy;也譯零拷貝)技術是指計算機執行操做時,CPU不須要先將數據從某處內存複製到另外一個特定區域。這種技術一般用於經過網絡傳輸文件時節省CPU週期和內存帶寬。 [1]
在web應用中,常常須要傳輸一些靜態文件(css, js, 圖片等),可講這一過程抽象爲下面兩個系統調度:linux
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
系統調用會進行上下文切換,共兩次上下文切換:web
用戶態 -> 內核態 -> 用戶態
上面的傳輸過程當中,共涉及4次上下文切換,4次數據複製,其流程以下圖
上圖中分爲兩部分,上半部分表示執行上下文(PC,寄存器等),下半部分表示數據區(堆棧等)
上班部分描繪了這一過程的上下文切換,下半部分描述了數據移動。緩存
在第一個區間裏(處於用戶態),執行read系統調度,讀取文件數據到tmp_buf中,所以會進行上下文切換,切換到內核態(第二區間),而後內核從磁盤中讀取文件數據到內核的緩衝區中(紅線所示,這種複製是利用DMA直接從磁盤複製到內存,不通過CPU的寄存器,因此稱爲DMA copy),接下來在將文件數據從內核緩衝區中複製到用戶緩衝區tmp_buf(藍色虛線所示,這種複製是先從內存到寄存器,而後寄存器到內核緩衝區,因此稱爲CPU copy),並切換回用戶態(第三個區間),此時read調用就完成了,文件數據存在tmp_buf中。安全
接下來進行write系統調用(處於第三個區間,用戶態),講tmp_buf的數據寫入socket中,首先進行上下文切換,進入內核態(第四個區間),而後講tmp_buf的數據複製到socket緩衝區中(藍色虛線所示),最後利用DMA從socket緩衝區將數據複製到網卡,而後切換回用戶態(第五個區間),此時wirte執行完成,可是數據可能尚未發送完成。網絡
當須要進行大量的上述操做時,上下文切換和內存複製就會嚴重的影響性能,爲此Linux內核提供了sendFile來解決這個文件。異步
首先kernel buffer和user buffer大小不必定相等。
kernel buffer的做用是預讀,每次調用read時不必定會觸發磁盤讀,只用當kernel buffer中的數據都被讀取完後,纔會觸發,而後從磁盤中多讀取一些數據到kernel buffer(從磁盤的讀取數據的大小,並不徹底取決於用戶執行的大小,還取決於kernel buffer的大小,以及文件的大小)。這樣當用戶屢次調用read讀取同一文件的數據時,就不須要每次都直接從硬盤中讀取,由於每次會多讀一些數據到kernel buffer中,這樣read就能夠直接從kernel buffer中讀取數據,而後複製到user buffer,這種作法在每次讀取數據量小於kernel buffer的大小時,能夠顯著的提升效率,可是當每次讀取數據量超過kernel buffer大小時,就會顯得低效了。socket
這樣作的緣由是爲了快速返回,從user buffer複製到kernel buffer的速度應該是快於從kernel buffer到網卡的,若是直接衝user buffer複製到網卡,會影響程序的性能。在將數據從user buffer複製到kernel buffer後,write就能夠返回了,剩下的就是利用DMA從kernel buffer讀取數據到網卡。
我認爲,這是阻塞io的作法,對於一些異步io,是能夠直接將user buffer的數據複製到網卡的(存疑,待之後解決)。性能
在Linux2.1中,sendfile的執行過程以下圖:
這裏只有一次系統調用,因此只有兩次上下文切換:用戶態 -> 內核態 -> 用戶態
數據複製有3次:磁盤 -> 內核緩衝區 -> socket緩衝區 -> 網卡
上述的複製種,從內核緩衝區到socket緩衝區顯得比較多餘,所以在Linux2.4對其進行了優化學習
在Linux2.4種,sendfile的執行過程以下圖:
關鍵的改動在於,將kernel buffer的信息添加到socket buffer,而後協議引擎利用這個信息,直接從kernel buffer讀取數據。可是這種操做,須要網卡支持gather操做。
零拷貝,雖然對提高程序性能有很大的幫助,可是對傳輸的文件的安全性沒有保證,至關於明文傳輸。
因爲文件直接從磁盤讀取到網絡,因此沒法對文件進行加密。所以對於須要對傳輸的數據進行加密的程序,如HTTPS,並不適用。
[1] 零複製
[2] 什麼是Zero-Copy?
[3] Zero-Copy&sendfile淺析
[4] Efficient data transfer through zero copy
[5] Zero Copy I: User-Mode Perspective