欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文徹底弄懂零拷貝原理以及java實現(xiàn)

 更新時間:2021年08月13日 10:27:53   作者:初念初戀  
零拷貝(英語: Zero-copy) 技術(shù)是指計算機(jī)執(zhí)行操作時,CPU不需要先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個特定區(qū)域,下面這篇文章主要給大家介紹了關(guān)于零拷貝原理以及java實現(xiàn)的相關(guān)資料,需要的朋友可以參考下

零拷貝

零拷貝(Zero-Copy)是一種 I/O 操作優(yōu)化技術(shù),可以快速高效地將數(shù)據(jù)從文件系統(tǒng)移動到網(wǎng)絡(luò)接口,而不需要將其從內(nèi)核空間復(fù)制到用戶空間。其在 FTP 或者 HTTP 等協(xié)議中可以顯著地提升性能。但是需要注意的是,并不是所有的操作系統(tǒng)都支持這一特性,目前只有在使用 NIO 和 Epoll 傳輸時才可使用該特性。

需要注意,它不能用于實現(xiàn)了數(shù)據(jù)加密或者壓縮的文件系統(tǒng)上,只有傳輸文件的原始內(nèi)容。這類原始內(nèi)容也包括加密了的文件內(nèi)容。

傳統(tǒng)I/O操作存在的性能問題

如果服務(wù)端要提供文件傳輸?shù)墓δ?,我們能想到的最簡單的方式是:將磁盤上的文件讀取出來,然后通過網(wǎng)絡(luò)協(xié)議發(fā)送給客戶端。

傳統(tǒng) I/O 的工作方式是,數(shù)據(jù)讀取和寫入是從用戶空間到內(nèi)核空間來回復(fù)制,而內(nèi)核空間的數(shù)據(jù)是通過操作系統(tǒng)層面的 I/O 接口從磁盤讀取或?qū)懭搿?/p>

代碼通常如下,一般會需要兩個系統(tǒng)調(diào)用:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

代碼很簡單,雖然就兩行代碼,但是這里面發(fā)生了不少的事情。

首先,期間共發(fā)生了 4 次用戶態(tài)與內(nèi)核態(tài)的上下文切換,因為發(fā)生了兩次系統(tǒng)調(diào)用,一次是 read() ,一次是 write(),每次系統(tǒng)調(diào)用都得先從用戶態(tài)切換到內(nèi)核態(tài),等內(nèi)核完成任務(wù)后,再從內(nèi)核態(tài)切換回用戶態(tài)。

上下文切換到成本并不小,一次切換需要耗時幾十納秒到幾微秒,雖然時間看上去很短,但是在高并發(fā)的場景下,這類時間容易被累積和放大,從而影響系統(tǒng)的性能。

其次,還發(fā)生了 4 次數(shù)據(jù)拷貝,其中兩次是 DMA 的拷貝,另外兩次則是通過 CPU 拷貝的,下面說一下這個過程:

  • 第一次拷貝,把磁盤上的數(shù)據(jù)拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)里,這個拷貝的過程是通過 DMA 搬運(yùn)的。
  • 第二次拷貝,把內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶的緩沖區(qū)里,于是我們應(yīng)用程序就可以使用這部分?jǐn)?shù)據(jù)了,這個拷貝到過程是由 CPU 完成的。
  • 第三次拷貝,把剛才拷貝到用戶的緩沖區(qū)里的數(shù)據(jù),再拷貝到內(nèi)核的 socket 的緩沖區(qū)里,這個過程依然還是由 CPU 搬運(yùn)的。
  • 第四次拷貝,把內(nèi)核的 socket 緩沖區(qū)里的數(shù)據(jù),拷貝到網(wǎng)卡的緩沖區(qū)里,這個過程又是由 DMA 搬運(yùn)的。

這種簡單又傳統(tǒng)的文件傳輸方式,存在冗余的上文切換和數(shù)據(jù)拷貝,在高并發(fā)系統(tǒng)里是非常糟糕的,多了很多不必要的開銷,會嚴(yán)重影響系統(tǒng)性能。

所以,要想提高文件傳輸?shù)男阅?,就需要減少「用戶態(tài)與內(nèi)核態(tài)的上下文切換」和「內(nèi)存拷貝」的次數(shù)。

零拷貝技術(shù)原理

零拷貝主要是用來解決操作系統(tǒng)在處理 I/O 操作時,頻繁復(fù)制數(shù)據(jù)的問題。關(guān)于零拷貝主要技術(shù)有 mmap+write、sendfile和splice等幾種方式。

虛擬內(nèi)存

在了解零拷貝技術(shù)之前,先了解虛擬內(nèi)存的概念。
所有現(xiàn)代操作系統(tǒng)都使用虛擬內(nèi)存,使用虛擬地址取代物理地址,主要有以下幾點(diǎn)好處:

  • 多個虛擬內(nèi)存可以指向同一個物理地址。
  • 虛擬內(nèi)存空間可以遠(yuǎn)遠(yuǎn)大于物理內(nèi)存空間。

利用上述的第一條特性可以優(yōu)化,可以把內(nèi)核空間和用戶空間的虛擬地址映射到同一個物理地址,這樣在 I/O 操作時就不需要來回復(fù)制了。

如下圖展示了虛擬內(nèi)存的原理。

mmap/write 方式

使用mmap/write方式替換原來的傳統(tǒng)I/O方式,就是利用了虛擬內(nèi)存的特性。下圖展示了mmap/write原理:

整個流程的核心區(qū)別就是,把數(shù)據(jù)讀取到內(nèi)核緩沖區(qū)后,應(yīng)用程序進(jìn)行寫入操作時,直接把內(nèi)核的Read Buffer的數(shù)據(jù)復(fù)制到Socket Buffer以便寫入,這次內(nèi)核之間的復(fù)制也是需要CPU的參與的。

上述流程就是少了一個 CPU COPY,提升了 I/O 的速度。不過發(fā)現(xiàn)上下文的切換還是4次并沒有減少,這是因為還是要應(yīng)用程序發(fā)起write操作。

那能不能減少上下文切換呢?這就需要sendfile方式來進(jìn)一步優(yōu)化了。

sendfile 方式

從 Linux 2.1 版本開始,Linux 引入了 sendfile來簡化操作。sendfile方式可以替換上面的mmap/write方式來進(jìn)一步優(yōu)化。

sendfile將以下操作:

  mmap();
  write();

替換為:

 sendfile();

這樣就減少了上下文切換,因為少了一個應(yīng)用程序發(fā)起write操作,直接發(fā)起sendfile操作。

下圖展示了sendfile原理:

sendfile方式只有三次數(shù)據(jù)復(fù)制(其中只有一次 CPU COPY)以及2次上下文切換。

那能不能把 CPU COPY 減少到?jīng)]有呢?這樣需要帶有 scatter/gather的sendfile方式了。

帶有 scatter/gather 的 sendfile方式

Linux 2.4 內(nèi)核進(jìn)行了優(yōu)化,提供了帶有 scatter/gather 的 sendfile 操作,這個操作可以把最后一次 CPU COPY 去除。其原理就是在內(nèi)核空間 Read BUffer 和 Socket Buffer 不做數(shù)據(jù)復(fù)制,而是將 Read Buffer 的內(nèi)存地址、偏移量記錄到相應(yīng)的 Socket Buffer 中,這樣就不需要復(fù)制。其本質(zhì)和虛擬內(nèi)存的解決方法思路一致,就是內(nèi)存地址的記錄。

下圖展示了scatter/gather 的 sendfile 的原理:

scatter/gather 的 sendfile 只有兩次數(shù)據(jù)復(fù)制(都是 DMA COPY)及 2 次上下文切換。CUP COPY 已經(jīng)完全沒有。不過這一種收集復(fù)制功能是需要硬件及驅(qū)動程序支持的。

splice 方式

splice 調(diào)用和sendfile 非常相似,用戶應(yīng)用程序必須擁有兩個已經(jīng)打開的文件描述符,一個表示輸入設(shè)備,一個表示輸出設(shè)備。與sendfile不同的是,splice允許任意兩個文件互相連接,而并不只是文件與socket進(jìn)行數(shù)據(jù)傳輸。對于從一個文件描述符發(fā)送數(shù)據(jù)到socket這種特例來說,一直都是使用sendfile系統(tǒng)調(diào)用,而splice一直以來就只是一種機(jī)制,它并不僅限于sendfile的功能。也就是說 sendfile 是 splice 的一個子集。

在 Linux 2.6.17 版本引入了 splice,而在 Linux 2.6.23 版本中, sendfile 機(jī)制的實現(xiàn)已經(jīng)沒有了,但是其 API 及相應(yīng)的功能還在,只不過 API 及相應(yīng)的功能是利用了 splice 機(jī)制來實現(xiàn)的。

和 sendfile 不同的是,splice 不需要硬件支持。

總結(jié)

無論是傳統(tǒng)的 I/O 方式,還是引入了零拷貝之后,2 次 DMA copy是都少不了的。因為兩次 DMA 都是依賴硬件完成的。所以,所謂的零拷貝,都是為了減少 CPU copy 及減少了上下文的切換。
下圖展示了各種零拷貝技術(shù)的對比圖:

CPU拷貝 DMA拷貝 系統(tǒng)調(diào)用 上下文切換
傳統(tǒng)方法 2 2 read/write 4
內(nèi)存映射 1 2 mmap/write 4
sendfile 1 2 sendfile 2
scatter/gather copy 0 2 sendfile 2
splice 0 2 splice 0

到此這篇關(guān)于零拷貝原理以及java實現(xiàn)的文章就介紹到這了,更多相關(guān)零拷貝原理及java實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在controller中如何設(shè)置接收參數(shù)的默認(rèn)值

    在controller中如何設(shè)置接收參數(shù)的默認(rèn)值

    這篇文章主要介紹了在controller中如何設(shè)置接收參數(shù)的默認(rèn)值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java基礎(chǔ)總結(jié)之Thymeleaf詳解

    Java基礎(chǔ)總結(jié)之Thymeleaf詳解

    Thymeleaf是一種現(xiàn)代的基于服務(wù)器端的Java模板引擎技術(shù),也是一個優(yōu)秀的面向Java的XML、XHTML、HTML5頁面模板,它具有豐富的標(biāo)簽語言、函數(shù)和表達(dá)式,在使用Spring Boot框架進(jìn)行頁面設(shè)計時,一般會選擇Thymeleaf模板,需要的朋友可以參考下
    2021-05-05
  • SpringBoot實現(xiàn)簡單文件上傳功能

    SpringBoot實現(xiàn)簡單文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了SpringBoot實現(xiàn)簡單文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java優(yōu)化if-else的11種方案

    java優(yōu)化if-else的11種方案

    If-Else結(jié)構(gòu)是一種常見的條件判斷語句,通過優(yōu)化If-Else結(jié)構(gòu),可以提高代碼的可讀性和執(zhí)行效率,本文主要介紹了java優(yōu)化if-else的11種方案,感興趣的可以了解一下
    2024-08-08
  • 如何查看java進(jìn)程內(nèi)存占用情況

    如何查看java進(jìn)程內(nèi)存占用情況

    這篇文章主要介紹了如何查看java進(jìn)程內(nèi)存占用情況問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • SpringSecurity使用PasswordEncoder加密用戶密碼的示例代碼

    SpringSecurity使用PasswordEncoder加密用戶密碼的示例代碼

    PasswordEncoder是Spring Security庫中的一個關(guān)鍵組件,它主要用于處理密碼的安全存儲和驗證,本文將給大家介紹一下SpringSecurity使用PasswordEncoder加密用戶密碼的方法,需要的朋友可以參考下
    2024-09-09
  • Java實現(xiàn)郵件發(fā)送的過程及代碼詳解

    Java實現(xiàn)郵件發(fā)送的過程及代碼詳解

    這篇文章主要介紹了Java實現(xiàn)郵件發(fā)送的過程及代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java?Swing實現(xiàn)記事本頁面

    Java?Swing實現(xiàn)記事本頁面

    這篇文章主要為大家詳細(xì)介紹了Java?Swing實現(xiàn)記事本頁面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解使用Spring Security進(jìn)行自動登錄驗證

    詳解使用Spring Security進(jìn)行自動登錄驗證

    本篇文章主要介紹了詳解使用Spring Security進(jìn)行自動登錄驗證,非常具有實用價值,需要的朋友可以參考下
    2017-09-09
  • redis 獲取 list 中的所有元素操作

    redis 獲取 list 中的所有元素操作

    這篇文章主要介紹了redis 獲取 list 中的所有元素操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03

最新評論