基於使用者緩衝區傳輸檔案時,過多的記憶體拷貝與上下文切換次數會降低效能。零拷貝技術在核心中完成記憶體拷貝,天然降低了記憶體拷貝次數。它通過一次系統呼叫合併了磁碟讀取與網路傳送兩個操作,降低了上下文切換次數。
尤其是,由於拷貝在核心中完成,它可以最大化使用 socket 緩衝區的可用空間,從而提高了一次系統呼叫中處理的資料量,進一步降低了上下文切換次數。零拷貝技術基於 pagecache,而 pagecache 快取了最近訪問過的資料,提公升了訪問快取資料的效能,同時,為了解決機械磁碟定址慢的問題,它還協助 io 排程演算法實現了 io 合併與預讀(這也是順序讀比隨機讀效能好的原因),這進一步提公升了零拷貝的效能。幾乎所有作業系統都支援零拷貝,如果應用場景就是把檔案傳送到網路中,那麼我們應當選擇使用了零拷貝的解決方案。
不過,零拷貝有乙個缺點,就是不允許程序對檔案內容作一些加工再傳送,比如資料壓縮後再傳送。另外,當 pagecache 引發負作用時,也不能使用零拷貝,此時可以用非同步 io+ 直接 io 替換。我們通常會設定乙個檔案大小閾值,針對大檔案使用非同步 io 和直接 io,而對小檔案使用零拷貝。
事實上 pagecache 對寫操作也有很大的效能提公升,因為 write 方法在寫入記憶體中的 pagecache 後就會返回,速度非常快,由核心負責非同步地把 pagecache 重新整理到磁碟中,這裡不再展開。
這一講我們從零拷貝出發,看到了檔案傳輸場景中核心在幕後所做的工作。這裡面的效能優化技術,要麼減少了磁碟的工作量(比如 pagecache 快取),要麼減少了 cpu 的工作量(比如直接 io),要麼提高了記憶體的利用率(比如零拷貝)。你在學習其他磁碟 io 優化技術時,可以延著這三個優化方向前進,看看究竟如何降低時延、提高併發能力。
思考
非同步 io 一定不會阻塞程序嗎?如果阻塞了程序,該如何解決呢?
1、如果這裡的非同步io指的是傳統的非同步阻塞io,比如select,epoll等。這種情況下是可能阻塞程序的,在核心通知使用者程序資料準備好了以後,使用者程序發起read呼叫,此時核心拷貝資料期間,程序實際上是阻塞的。
解決方案:可以在核心完成拷貝後再通知使用者程序,或者使用mmap方式,使用者態和核心實際上是同一塊記憶體就不存在拷貝了。
2、如果這裡的非同步io指的是linux核心2.6版本之後的aio,那麼不太可能阻塞程序,除非系統核心之後一直排程不到該程序(比如其他任務不斷的搶占式或繫結核心執行)。
解決方案:可以使用繫結核心的執行機制阻值其他高優先順序程序或中斷進行搶占。
如何高效傳輸檔案之零拷貝
pagecache 磁碟快取記憶體 大檔案零拷貝下的問題 非同步io 直接io 總結磁碟是主機中最慢的硬體,往往是效能的瓶頸,優化它能獲得立竿見影的效果。針對磁碟的優化技術有零拷貝 直接io 非同步io等 主要目的是為了降低時延 提公升作業系統的吞吐量,圍繞著核心的磁碟快取記憶體 pagecache...
零拷貝 如何高效的通過網路傳輸檔案
假如要傳輸320mb的檔案,那麼你可能會在應用程式分配32kb的記憶體空間,然後呼叫read函式從檔案中讀出32位元組,最後呼叫write函式通過網路發生出去,其流程如下圖所示。這種方式非常低效,主要有如下的原因 1 至少經歷了4萬次使用者態與核心態的上下文切換。因為每處理32kb的訊息,就需要一次...
什麼是零拷貝?一招學會高效傳輸檔案
差一點我們就擦肩而過了 有趣有用 有態度 導學問題 1.伺服器通過網路傳輸資料時,系統有幾次拷貝?2.大檔案和小檔案各有什麼傳輸特點?零拷貝 zero copy 技術指在計算機執行操作時,cpu 不需要先將資料從乙個記憶體區域複製到另乙個記憶體區域,從而可以減少上下文切換以及 cpu 的拷貝時間。某...