1. 程式人生 > >Linux 4 15核心TCP的重傳佇列變成紅黑樹了

Linux 4 15核心TCP的重傳佇列變成紅黑樹了

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                       

閒來check一下Linux TCP實現近期的patch,有一個即將進入4.15核心的讓我比較感興趣,TCP終於將傳輸佇列

重傳佇列分離了開來。該patch的說明如下:
tcp: implement rb-tree based retransmit queue https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=75c119afe14f74b4dd967d75ed9f57ab6c0ef045

曾經,這兩個佇列是重合的,就像下面這樣:

這裡寫圖片描述

然而,在4.15核心,卻變成了下面的樣子:

這裡寫圖片描述

重傳佇列成了一棵單獨的紅黑樹,只要是傳送過而沒有被ACK確認(即沒有被UNA指標覆蓋)的資料包,均從傳輸佇列斷開而加入一棵紅黑樹。我接下來簡單說一下這個改變為什麼是一件好事。

  如果重傳佇列僅僅是一個連結串列,那麼如果想在其中找到某一個數據包的話,除了遍歷別無他法。而我們知道,遍歷操作的時間複雜度是O(n),是n非常大的時候,這將是一個比較耗時的操作。我們再來想一下什麼時候需要遍歷。很簡單,就是在收到攜帶SACK選項的ACK段時,需要在重傳佇列中找到那些資料包是被SACK的,然後標記它們,如果重傳佇列非常長,那麼遍歷操作將會消耗很多的CPU時間。

  如補丁說明中所述,以往,人們以各種各樣的理由抵制對這個遍歷操作進行優化,其歸根結底無非就是優化帶來的收益很小,但卻增加了很大的實現複雜性,優化帶來的收益很小的原因無非僅僅在於“一般而言,重傳佇列都很短!”。這麼想是對的,但也只是曾經。因為曾經的網路頻寬是很低的,同時對端的接收快取也是很小的,這意味著TCP的擁塞視窗以及接收視窗都不會太大。如果說重傳佇列很短,當然不必去故弄玄虛將重傳佇列獨立起來作為一個可以高效查詢的資料結構存在了。

  但,現在的情況和以前不一樣了。目前的網路頻寬動輒10G以上,機器記憶體動輒16G以上,TCP擁塞控制演算法也迎來了BBR新時代,因此TCP的傳送視窗自然而然也就劇增了,隨之TCP的重傳佇列自然而然變得非常之長。人們一向不太在意的問題,此時便顯得尤為重要,優化這個遍歷資料結構迫在眉睫。因此將其從連結串列獨立成一棵紅黑樹便是自然而然的事情了。

  在去年的時候曾經想過這個問題,但當時由於幾乎沒有碰到過真實情況下10G以上的頻寬,就覺得這是沒有意義的,直到現在我也沒碰到過哪怕超過1G的公網TCP傳輸頻寬,所以這個優化依然顯得沒有必要,然而這個patch看起來是如此的有道理,而且也是自己曾經考慮過的,為它多寫幾筆是應該的。


除了高效的查詢之外,在用紅黑樹替代連結串列之後,我覺得還有一個好處,那就是簡化了整個tcp_sacktag_write_queue函式以及其呼叫函式的程式碼。曾經何時,這些函式讓多少人頭疼不已,用紅黑樹替代連結串列操作之後,相信程式碼會清晰很多,自然很多人就很容易看懂了。

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述