看板 Audiophile
繼前一篇 #1cWInSDW 分享第三層交換器優先權設定之後,這篇來分享一旦資料進入 網卡後,如何再優化 Linux 作業系統內部的資料流;這裡一樣是只探討優化手法, 不討論音質的改變(YMMV...) 關於 Receive Side Scaling, RSS 相關說明文件在此: https://tinyurl.com/5d9zuace RSS 也算是一個古老的存在了,許多高負載伺服器也都會運用這個功能去分攤/處理 所接收的資料流。其運作原理是根據來源地址、來源埠、目的位址及目的埠,送入 一個叫 Toeplitz(預設)的矩陣去換算出 hash 值,再用這個 hash 去對應的接受 儲列。例如,我的 HQPlayer Embedded 主機接收 NFS 的資料,根據相關地址和埠, 會交給儲列 8 來處理: https://imgur.com/pr9YHN4.jpg
管理者即能用這個機制,用 ethtool 去分配特定服務給特定軟體所在的 CPU 接收 資料,來減少資料延遲。 在音訊網路裡面,能想到的大概是 Roon -> RoonBridge 或是 Roon -> HQPlayer -> NAA 這樣的傳遞接收路徑;RSS 的設定方式大同小異,這裡就用我的 NAA <-> Ravenna bridge 做個例子,好處是內核設定的改動,都能反映在 Ravenna 器材上 的接收狀態。 我的 NAA 是 Intel Atom x7425e 四核心的單板電腦,跑 Ubuntu 實時核心,有特別 隔離一顆 CPU 核心做其他的事情。開完機之後我們可以看到由於 CPU 為四核心, RxTx 儲列會有四個(RxTx-0~RxTx-3),但因為我把第四個 CPU 核心獨立出來不受 干擾,因此儲列的 IRQ 會自動轉分佈在前三個 CPU 核心。 https://imgur.com/WIDo1Xp.jpg
但 RSS indirection table 的數值仍是指向四個 Rx 儲列,這表示仍有一個 CPU 核心要處理兩個 Rx 儲列: https://imgur.com/x3pAL70.jpg
如果不去變動 RSS 等設定的話,NAA 交給 Ravenna 的資料,Ravenna 接收端會呈現 一些鋸齒狀: https://imgur.com/MMe9OOY.jpg
這些鋸齒狀都還是在容許範圍內,因此不會造成音訊中斷/爆音/破音/雜音等問題, 只是看起來不舒服。 不知為何 x7425e 並未支援 hash key,手上工具算不出來資料流會走哪個儲列, 因此策略上我個人是採取「機會均等」,讓 enp1s0 這個負責 NAA 的網口所接收的 資料平均分給三個 Rx 儲列,指令: ethtool -X enp1s0 equal 3 (enp1s0 是我的網口名稱,請自行代入自己機器抓出的網口名稱。) 這樣就能把 RSS indirection table 強制平均分配到三個 Rx 儲列: https://imgur.com/cjcLxHo.jpg
接下來再用 Receive Packet Steering, RPS 技巧,將 Rx 的儲列重新順給 CPU 第 0, 1, 2 核上,指令: echo 1 > /sys/class/net/enp1s0/queues/rx-0/rps_cpus echo 2 > /sys/class/net/enp1s0/queues/rx-1/rps_cpus echo 4 > /sys/class/net/enp1s0/queues/rx-2/rps_cpus 1,2,4 是二進位遮罩轉為十進位數值,二進位最右邊是第一顆 CPU 核心,因此我 指定某個 Rx 儲列由 CPU 第三顆核心處理的話,二進位遮罩是 0100,換算十進位 是 4,以此類推。 Rx 儲列安排好之後,當然最理想是 IRQ 也一併和 Rx 儲列調整,前面截圖已知 RxTx-0, RxTx-1, RxTx-2 的 IRQ 分別是 128, 129, 130,我們就可以指定 IRQ 給相對的 CPU 核心: echo 0 > /proc/irq/128/smp_affinity_list echo 1 > /proc/irq/129/smp_affinity_list echo 2 > /proc/irq/130/smp_affinity_list (當然在做這個設定之前,要將 irqbalance 守護程式整個關掉。) 截圖呈現三個 RxTx 儲列的 IRQ 分別交給 CPU 0, 1, 2 https://imgur.com/QETjXby.jpg
為了配合這個 Rx 儲列硬平均,我也指定 networkaudiod 這個 daemon 跑在負責這 三個儲列的 CPU 核心上(networkaudiod 的主體 thread 會在這三個 CPU 核心上 隨機跑動)。 不過這也還是單位時間內 33% 機率資料流會被 networkaudiod 的主 thread 吃到, 因此還可以再用 Receive Flow Steering, RPS 來輔助資料流導向的命中率,這個 部分因為服務單純,因此 flow table 大小我並沒有設很大,這部分就看個人的 需求而定: echo 8192 > /proc/sys/net/core/rps_sock_flow_entries 其他 Rx 儲列的 flow table 必須小於主 table size,我是設定 1024: echo 1024 > /sys/class/net/enp1s0/queues/rx-0/rps_flow_cnt echo 1024 > /sys/class/net/enp1s0/queues/rx-1/rps_flow_cnt echo 1024 > /sys/class/net/enp1s0/queues/rx-2/rps_flow_cnt NAA 經過 RSS + RPS + RFS 的調整之後,Ravenna 器材接收端變平順了些: https://imgur.com/wZia5OZ.jpg
若您的 endpoint 是小電腦,不妨試著調整看看,或許會有驚喜 :-) (以上的調整是採 run-time 方式調整,若會寫 shell script 就能省很多事,但 這裡就不是主題範圍了...) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.163.96.58 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Audiophile/M.1720332088.A.EE3.html ※ 編輯: elguapo (118.163.96.58 臺灣), 07/07/2024 14:34:39
iitze: 推專業 07/07 16:00
djboy: 專業給推 07/10 10:38
l98: 太 HARDCORE 了 07/10 10:40
goldie: 看不懂XD,推! 07/14 20:05