首先是Receive Packet Steering (RPS)
隨著單核CPU速度已經達到極限,CPU向多核方向發展,要持續提高網絡處理帶寬,傳統的提升硬件設備、智能處理(如GSO、TSO、UFO)處理辦法已不足夠。如何充分利用多核優勢來進行並行處理提高網絡處理速度就是RPS解決的課題。
以一個具有8核CPU和一個NIC的,連接在網絡中的主機來說,對於由該主機產生並通過NIC發送到網絡中的數據,CPU核的並行性是自熱而然的事情:
問題主要在於當該主機通過NIC收到從網絡發往本機的數據包時,應該將數據包分發給哪個CPU核來處理(有些具有多條接收隊列和多重中斷線路的NIC可以幫助數據包並行分發,這裏考慮普通的NIC,普通的NIC通過RPS來模擬實現並行分發):
普通的NIC來分發這些接收到的數據包到CPU核處理需要一定的知識智能以幫助提升性能,如果數據包被任意的分配給某個CPU核來處理就可能會導致所謂的“CACHELINE-PINGPONG”現象:
比如DATA0數據流的第一個包被分發給CPU0來處理,第二個包分發給CPU1處理,第三個包又分發給CPU0處理;而DATA1數據流恰好相反。這樣的交替輪換(8核情況交替得更隨意)會導致CPU核的CACHE利用過分抖動。
RPS就是消除這種CPU核隨意性分配的智能知識,它通過數據包相關的信息(比如IP地址和端口號)來創建CPU核分配的hash表項,當一個數據包從NIC轉到內核網絡子系統時就從該hash表內獲取其對應分配的CPU核(首次會創建表項)。這樣做的目的很明顯,它將具有相同相關信息(比如IP地址和端口號)的數據包都被分發給同一個CPU核來處理,避免了CPU的CACHE抖動現象,提高處理性能。
有兩點細節:第一,所有CPU核具有等同的被綁定幾率,但管理員可以明確設置CPU核的綁定情況;第二,hash表項的計算是由NIC進行的,不消耗CPU。
RPS的性能優化結果為大致可提升3倍左右。tg3驅動的NIC性能由90,000提升到285,000,而e1000驅動的NIC性能由90,000提升到292,000,其它驅動NIC也得到類似的測試結果。
接下來是Receive flow steering (RFS)
RFS是在RPS上的改進,從上面的介紹可以看到,通過RPS已經可以把同一流的數據包分發給同一個CPU核來處理了,但是有可能出現這樣的情況,即給該數據流分發的CPU核和執行處理該數據流的應用程序的CPU核不是同一個:
不僅要把同一流的數據包分發給同一個CPU核來處理,還要分發給其‘被期望’的CPU核來處理就是RFS需要解決的問題。
RFS會創建兩個與數據包相關信息(比如IP地址和端口號)的CPU核映射hash表:
1.一個用於表示期望處理具有該類相關信息數據包的CPU核映射,通過recvmsg()或sendmsg()等系統調用信息來創建該hash表(稱之為期望CPU表)。比如運行於CPU0核上的某應用程序調用了recvmsg()從遠程機器host1上獲取數據,那麽NIC對從host1上發過來的數據包的分發期望CPU核就是CPU0。
2.一個用於表示最近處理過具有該類相關信息數據包的CPU核映射,稱這種表為當前CPU表。該表的存在是因為有多線程的情況,比如運行在兩個CPU核上的多線程程序(每個核運行一個線程)交替調用recvmsg()系統函數從同一個socket上獲取遠程機器host1上的數據會導致期望CPU表頻繁更改。如果數據包的分發僅由期望CPU表決定則會導致數據包交替分發到這兩個CPU核上,很明顯,這不是我們想要的效果。
既然CPU核的分配由兩個hash表值決定,那麽就可以有一個算法來描述這個決定過程:
1.如果當前CPU表對應表項未設置或者當前CPU表對應表項映射的CPU核處於離線狀態,那麽使用期望CPU表對應表項映射的CPU核。
2.如果當前CPU表對應表項映射的CPU核和期望CPU表對應表項映射的CPU核為同一個,那麽好辦,就使用這一個核。
3.如果當前CPU表對應表項映射的CPU核和期望CPU表對應表項映射的CPU核不為同一個,那麽:
a)如果同一流的前一段數據包未處理完,那麽必須使用當前CPU表對應表項映射的CPU核,以避免亂序。
b)如果同一流的前一段數據包已經處理完,那麽則可以使用期望CPU表對應表項映射的CPU核。
算法的前兩步比較好理解,而對於第三步可以用下面兩個圖來幫助理解。應用程序APP0有兩個線程THD0和THD1分別運行在CPU0核和CPU1核上,同時CPU1核上還運行有應用程序APP1。首先THD1調用recvmsg()獲取遠程數據(數據流稱之為FLOW0),此時FLOW0的期望CPU核為CPU1,隨著數據塊FLOW0 : 0的到來並交給CPU1核處理,此時FLOW0的當前CPU核也為CPU1。如果此時THD0也在同一個socket上調用recvmsg()獲取遠程數據(數據流同樣也是FLOW0),那麽FLOW0的期望CPU核就改變為CPU0(當前CPU核仍然為CPU1)。與此同時,NIC收到數據塊FLOW0 : 1,如何將該數據塊分發給CPU核就到了上面算法的第三步。
分情況判斷:
1.如果同一流的前一段數據包FLOW0 : 0未處理完,那麽必須使用當前CPU核CPU1來處理新到達的數據塊,以避免亂序。如下圖所示(FLOW1流是應用程序APP1的):
2.如果同一流的前一段數據包FLOW0 : 0已經處理完畢,那麽可以使用期望CPU核CPU0來處理新到達的數據塊。如下圖所示(FLOW1流是應用程序APP1的):
RFS適用於面向流的網絡協議,它能更好的提升CPU的CACHE效率,不論是內核還是應用程序本身。RFS的性能優化結果在普通環境下為大致可提升3倍左右,而在多線程環境大致可提升2倍。能通過軟件的形式提升機器網絡帶寬性能自然也是再好不過的事情了。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 多層分類 的頭像
    多層分類

    多層分類的部落格

    多層分類 發表在 痞客邦 留言(0) 人氣()