如何高效傳輸檔案之零拷貝

2021-10-11 14:43:11 字數 2962 閱讀 9579

pagecache 磁碟快取記憶體

大檔案零拷貝下的問題

非同步io+直接io

總結磁碟是主機中最慢的硬體,往往是效能的瓶頸,優化它能獲得立竿見影的效果。

針對磁碟的優化技術有零拷貝、直接io、 非同步io等

主要目的是為了降低時延、提公升作業系統的吞吐量,圍繞著核心的磁碟快取記憶體(pagecache)去減少cpu和磁碟裝置的工作量。

現在假設服務端有資料大小為320mb的檔案,要將這個資料通過網路傳送給客戶端,在記憶體中分配32kb的緩衝區進行傳送。

伺服器提供檔案傳輸功能,需要將磁碟上的檔案讀取出來,通過網路協議這邊傳送到客戶端。320mb的檔案傳輸過程如下:

由於核心緩衝區page cache只有32kb,所以需要把檔案分成1萬份傳送,一次32kb傳送過程如下:

所以提公升效能的關鍵在於

降低上下文切換頻率

讀取磁碟和操作網絡卡都是由作業系統核心完成,核心和使用者程序工作環境完全不同,只要我們執行read、write系統呼叫,一定會發生2次上下文切換:

減少上下文切換次數方案:把read、write兩次系統呼叫合併成一次,在核心中完成磁碟與網絡卡的資料互動。

減少記憶體拷貝次數

每個週期中有4次拷貝,其中兩次和物理裝置相關的拷貝是必不可少的,所以我們優化的主要方向為使用者緩衝區的兩次拷貝,本質上著兩個都沒有必要,如圖中拷貝2和拷貝3

如果核心在讀取檔案後,直接把 pagecache 中的內容拷貝到 socket 緩衝區,待到網絡卡傳送完畢後,再通知程序,這樣就只有 2 次上下文切換,和 3 次記憶體拷貝。

如果網絡卡支援 sg-dma(the scatter-gather direct memory access)技術,還可以再去除 socket 緩衝區的拷貝,這樣一共只有 2 次記憶體拷貝。

這個就是零拷貝技術。sendfile是作業系統提供的新函式,同時接收檔案描述符和tcp socket作為輸入引數,執行時可以完全可以在核心態完成記憶體拷貝,減少了記憶體拷貝次數,降低了上下文切換次數。

零拷貝如何利用socket 緩衝區記憶體

零拷貝取消了使用者緩衝區後,在核心態完成資料拷貝

使用者記憶體為什麼分配32kb

socket緩衝區的可用空間大小是動態變化的,所以使用者快取區無法socket緩衝區設定成一致,受到tcp滑動視窗、應用緩衝區、整個系統的影響。

所以綜合權衡下最終選了32kb。

零拷貝使我們不用關心socket緩衝區的大小,呼叫零拷貝傳送方法時,盡可能把檔案位元組數設定為未傳送的自己數,比如320mb,會根據socket緩衝區大小傳送資料,假如socket緩衝區大小為1.4mb,那麼就會傳送1.4mb,會比32kb,提公升很多效率

綜上分析,零拷貝通過降低上下文切換、記憶體拷貝把效能提高至少一倍以上。

零拷貝還使用了pagecache技術,可以通過它進一步提公升效能

上面幾張圖中,讀取檔案都是先把檔案拷貝到pagecache上,再拷貝到程序中,這麼做的原因如下:

例如 read 方法只讀取了 0-32kb 的位元組,但核心會把其後的 32-64kb 也讀取到 pagecache,後32kb 讀取的成本很低。如果在 32-64kb 淘汰出 pagecache 前,程序讀取到它了,收益就非常大

所以大檔案不應該使用pagecache,也不應該使用零拷貝技術處理。

高併發場景處理大檔案用非同步io和直接io來替換零拷貝技術。

呼叫read方法讀取檔案時,阻塞等待過程如下

非同步io可以解決阻塞問題,操作分為兩部分:

非同步io沒有拷貝到pagecache中,是非同步io實現上的缺陷

經過pagecache的io叫做快取io,與虛擬記憶體系統耦合太緊,導致非同步io不支援快取io

繞過pagecache的io是直接io,非同步io只支援直接io。

直接io的應用場景:

直接io的缺點:不能享受以下效能提公升

大小檔案的判斷,可以靈活配置:nginx 的 directio 指令

基於使用者緩衝區傳輸檔案時,過多的記憶體拷貝與上下文切換次數會降低效能。

零拷貝技術在核心中完成記憶體拷貝,天然降低了記憶體拷貝次數。

通過一次系統呼叫合併了磁碟讀取與網 絡傳送兩個操作,降低了上下文切換次數。

由於拷貝在核心中完成,它可以最大化使用 socket 緩衝區的可用空間,從而提高了一次系統呼叫中處理的資料量,進一步降低了 上下文切換次數。

零拷貝技術基於 pagecache,而 pagecache 快取了最近訪問過的資料,提公升了訪問快取 資料的效能,同時,為了解決機械磁碟定址慢的問題,它還協助 io 排程演算法實現了 io 合 並與預讀(這也是順序讀比隨機讀效能好的原因),這進一步提公升了零拷貝的效能。

幾乎所有作業系統都支援零拷貝,如果應用場景就是把檔案傳送到網路中,那麼我們應當選擇使用 了零拷貝的解決方案。

不過,零拷貝有乙個缺點,就是不允許程序對檔案內容作一些加工再傳送,比如資料壓縮後再傳送。另外,當 pagecache 引發負作用時,也不能使用零拷貝,此時可以用非同步 io+ 直接 io 替換。我們通常會設定乙個檔案大小閾值,針對大檔案使用非同步 io 和直接 io,而 對小檔案使用零拷貝。

事實上 pagecache 對寫操作也有很大的效能提公升,因為 write 方法在寫入記憶體中的 pagecache 後就會返回,速度非常快,由核心負責非同步地把 pagecache 重新整理到磁碟中。

磁碟 io 優化技術三個方向

零拷貝 高效地傳輸檔案

基於使用者緩衝區傳輸檔案時,過多的記憶體拷貝與上下文切換次數會降低效能。零拷貝技術在核心中完成記憶體拷貝,天然降低了記憶體拷貝次數。它通過一次系統呼叫合併了磁碟讀取與網路傳送兩個操作,降低了上下文切換次數。尤其是,由於拷貝在核心中完成,它可以最大化使用 socket 緩衝區的可用空間,從而提高了一次...

零拷貝 如何高效的通過網路傳輸檔案

假如要傳輸320mb的檔案,那麼你可能會在應用程式分配32kb的記憶體空間,然後呼叫read函式從檔案中讀出32位元組,最後呼叫write函式通過網路發生出去,其流程如下圖所示。這種方式非常低效,主要有如下的原因 1 至少經歷了4萬次使用者態與核心態的上下文切換。因為每處理32kb的訊息,就需要一次...

什麼是零拷貝?一招學會高效傳輸檔案

差一點我們就擦肩而過了 有趣有用 有態度 導學問題 1.伺服器通過網路傳輸資料時,系統有幾次拷貝?2.大檔案和小檔案各有什麼傳輸特點?零拷貝 zero copy 技術指在計算機執行操作時,cpu 不需要先將資料從乙個記憶體區域複製到另乙個記憶體區域,從而可以減少上下文切換以及 cpu 的拷貝時間。某...