Monibuca v5 實現零拷貝BufReader

背景

在開發高 IO 的程序都會面臨一個問題,就是如何提供從網絡層讀取數據的性能。

直接讀取

直接讀取類似下面這種情況

b:= make(100)
io.ReadFull(conn,b)

優點是簡單,而且延遲較低,可以立即獲取到想要長度的數據。缺點也很明顯,需要頻繁 make,更關鍵的是需要頻繁調用 syscall,造成 CPU 損耗。

使用 bufio.Reader

這個是標準庫提供的,帶緩衝的讀取方式

reader:=bufio.NewReader(conn)
b:= make(100)
io.ReadFull(reader,b)

原理是一次讀入 4096(默認)的數據到緩存中,減少多次 syscall 。然後再從緩存中讀取需要的數據,不夠再從網絡測讀取。

但是:

  • 沒有解決需要 make 導致的 gc 問題
  • 增加了內存複製操作

 

基於 v5 內存分配器實現的零拷貝BufReader

v5 的內存分配器看這篇:《v5 中實現優雅內存分配器

基本原理:

  1. 從分配器裏面獲取一塊內存作爲緩存
  2. 一次讀入一大塊數據到緩存中
  3. 緩存中再讀取需要的數據,並且可以手動控制回收部分內存

當音視頻數據在 ringbuffer 中將要被覆蓋的時候,就把對應的內存回收。其他臨時的數據(比如長度、時間戳等),都可以在使用完後立即回收。

 

橘色的內存塊是黃色的切片,因此不需要拷貝就能直接使用,在音視頻數據的緩存過程中也保持碎片形式,不進行合併操作,在發送的時候使用 writev 批量發送就避免了內存複製。後續可以再結合更底層的網絡 IO 庫進行進一步的優化底層傳輸效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章