socket效能優化 上

2021-08-26 14:13:23 字數 4216 閱讀 3266

socket效能優化(上)

2023年01月01日

[b]socket效能優化[/b]

m. tim jones (), 資深軟體工程師, emulex

使用 sockets api,我們可以開發客戶機和伺服器應用程式,它們可以在本地網路上進行通訊,也可以通過 internet 在全球範圍內進行通訊。與其他 api 一樣,您可以通過一些方法使用 sockets api,從而提高 socket 的效能,或者限制 socket 的效能。本文探索了 4 種使用 sockets api 來獲取應用程式的最大效能並對 gnu/linux? 環境進行優化從而達到最好結果的方法。

在開發 socket 應用程式時,首要任務通常是確保可靠性並滿足一些特定的需求。利用本文中給出的 4 個提示,您就可以從頭開始為實現最佳效能來設計並開發 socket 程式。本文內容包括對於 sockets api 的使用、兩個可以提高效能的 socket 選項以及 gnu/linux 優化。

為了能夠開發效能卓越的應用程式,請遵循以下技巧:

最小化報文傳輸的延時。 最小化系統呼叫的負載。 為 bandwidth delay product 調節 tcp 視窗。 動態優化 gnu/linux tcp/ip 棧。

技巧 1. 最小化報文傳輸的延時

在通過 tcp socket 進行通訊時,資料都拆分成了資料塊,這樣它們就可以封裝到給定連線的 tcp payload(指 tcp 資料報中的有效負荷)中了。tcp payload 的大小取決於幾個因素(例如最大報文長度和路徑),但是這些因素在連線發起時都是已知的。為了達到最好的效能,我們的目標是使用盡可能多的可用資料來填充每個報文。當沒有足夠的資料來填充 payload 時(也稱為最大報文段長度(maximum segment size) 或 mss),tcp 就會採用 nagle 演算法自動將一些小的緩衝區連線到乙個報文段中。這樣可以通過最小化所傳送的報文的數量來提高應用程式的效率,並減輕整體的網路擁塞問題。

儘管 john nagle 的演算法可以通過將這些資料連線成更大的報文來最小化所傳送的報文的數量,但是有時您可能希望只傳送一些較小的報文。乙個簡單的例子是 telnet 程式,它讓使用者可以與遠端系統進行互動,這通常都是通過乙個 shell 來進行的。如果使用者被要求用傳送報文之前輸入的字元來填充某個報文段,那麼這種方法就絕對不能滿足我們的需要。

另外乙個例子是 http 協議。通常,客戶機瀏覽器會產生乙個小請求(一條 http 請求訊息),然後 web 伺服器就會返回乙個更大的響應(web 頁面)。

[b]解決方案[/b]

但是在需要最小化傳輸延時的情況中,sockets api 可以提供一種解決方案。要禁用 nagle 演算法,您可以設定 tcp_nodelay socket 選項,如清單 1 所示。

[b]清單 1. 為 tcp socket 禁用 nagle 演算法[/b]

int sock, flag, ret;/* create new stream socket */sock = [b]socket[/b]( af_inet, sock_stream, 0 );/* disable the nagle (tcp no delay) algorithm */flag = 1;ret = [b]setsockopt[/b]( sock, ipproto_tcp, tcp_nodelay, (char *)&flag, sizeof(flag) );if (ret == -1)

技巧 2. 最小化系統呼叫的負載

任何時候通過乙個 socket 來讀寫資料時,您都是在使用乙個系統呼叫(system call)。這個呼叫(例如 read 或 write)跨越了使用者空間應用程式與核心的邊界。另外,在進入核心之前,您的呼叫會通過 c 庫來進入核心中的乙個通用函式(system_call())。從 system_call() 中,這個呼叫會進入檔案系統層,核心會在這兒確定正在處理的是哪種型別的裝置。最後,呼叫會進入 socket 層,資料就是在這裡進行讀取或進行排隊從而通過 socket 進行傳輸的(這涉及資料的副本)。

這個過程說明系統呼叫不僅僅是在應用程式和核心中進行操作的,而且還要經過應用程式和核心中的很多層次。這個過程耗費的資源很高,因此呼叫次數越多,通過這個呼叫鏈進行的工作所需要的時間就越長,應用程式的效能也就越低。

由於我們無法避免這些系統呼叫,因此惟一的選擇是最小化使用這些呼叫的次數。幸運的是,我們可以對這個過程進行控制。

[b]解決方案[/b]

在將資料寫入乙個 socket 時,盡量一次寫入所有的資料,而不是執行多次寫資料的操作。對於讀操作來說,最好傳入可以支援的最大緩衝區,因為如果沒有足夠多的資料,核心也會試圖填充整個緩衝區(另外還需要保持 tcp 的通告視窗為開啟狀態)。這樣,您就可以最小化呼叫的次數,並可以實現更好的整體效能。

技巧 3. 為 bandwidth delay product 調節 tcp 視窗

tcp 的效能取決於幾個方面的因素。兩個最重要的因素是鏈結頻寬(link bandwidth)(報文在網路上傳輸的速率)和 往返時間(round-trip time) 或 rtt(傳送報文與接收到另一端的響應之間的延時)。這兩個值確定了稱為 bandwidth delay product(bdp)的內容。

給定鏈結頻寬和 rtt 之後,您就可以計算出 bdp 的值了,不過這代表什麼意義呢?bdp 給出了一種簡單的方法來計算理論上最優的 tcp socket 緩衝區大小(其中儲存了排隊等待傳輸和等待應用程式接收的資料)。如果緩衝區太小,那麼 tcp 視窗就不能完全開啟,這會對效能造成限制。如果緩衝區太大,那麼寶貴的記憶體資源就會造成浪費。如果您設定的緩衝區大小正好合適,那麼就可以完全利用可用的頻寬。下面我們來看乙個例子:

bdp = link_bandwidth * rtt

如果應用程式是通過乙個 100mbps 的區域網進行通訊,其 rrt 為 50 ms,那麼 bdp 就是:

100mbps * 0.050 sec / 8 = 0.625mb = 625kb

[b]注意:[/b]此處除以 8 是將位轉換成通訊使用的位元組。

因此,我們可以將 tcp 視窗設定為 bdp 或 1.25mb。但是在 linux 2.6 上預設的 tcp 視窗大小是 110kb,這會將連線的頻寬限制為 2.2mbps,計算方法如下:

throughput = window_size / rtt

110kb / 0.050 = 2.2mbps

如果使用上面計算的視窗大小,我們得到的頻寬就是 12.5mbps,計算方法如下:

625kb / 0.050 = 12.5mbps

差別的確很大,並且可以為 socket 提供更大的吞吐量。因此現在您就知道如何為您的 socket 計算最優的緩衝區大小了。但是又該如何來改變呢?

[b]解決方案[/b]

sockets api 提供了幾個 socket 選項,其中兩個可以用於修改 socket 的傳送和接收緩衝區的大小。清單 2 展示了如何使用 so_sndbuf 和 so_rcvbuf 選項來調整傳送和接收緩衝區的大小。

[b]注意:[/b]儘管 socket 緩衝區的大小確定了通告 tcp 視窗的大小,但是 tcp 還在通告視窗內維護了乙個擁塞視窗。因此,由於這個擁塞視窗的存在,給定的 socket 可能永遠都不會利用最大的通告視窗。

[b]清單 2. 手動設定傳送和接收 socket 緩衝區大小[/b]

int ret, sock, sock_buf_size;sock = [b]socket[/b]( af_inet, sock_stream, 0 );sock_buf_size = bdp;ret = [b]setsockopt[/b]( sock, sol_socket, so_sndbuf, (char *)&sock_buf_size, sizeof(sock_buf_size) );ret = [b]setsockopt[/b]( sock, sol_socket, so_rcvbuf, (char *)&sock_buf_size, sizeof(sock_buf_size) );

在 linux 2.6 核心中,傳送緩衝區的大小是由呼叫使用者來定義的,但是接收緩衝區會自動加倍。您可以進行 getsockopt 呼叫來驗證每個緩衝區的大小。

[b]巨幀(jumbo frame)[/b]

我們還可以考慮將包的大小從 1,500 位元組修改為 9,000 位元組(稱為巨幀)。在本地網路中可以通過設定最大傳輸單元(maximum transmit unit,mtu)來設定巨幀,這可以極大地提高效能。

就 window scaling 來說,tcp 最初可以支援最大為 64kb 的視窗(使用 16 位的值來定義視窗的大小)。採用 window scaling(rfc 1323)擴充套件之後,您就可以使用 32 位的值來表示視窗的大小了。gnu/linux 中提供的 tcp/ip 棧可以支援這個選項(以及其他一些選項)。

socket效能優化 上

socket效能優化 上 2012年01月01日 b socket效能優化 b m.tim jones 資深軟體工程師,emulex 使用 sockets api,我們可以開發客戶機和伺服器應用程式,它們可以在本地網路上進行通訊,也可以通過 internet 在全球範圍內進行通訊。與其他 api 一...

socket效能優化 上

socket效能優化 上 2012年01月01日 b socket效能優化 b m.tim jones 資深軟體工程師,emulex 使用 sockets api,我們可以開發客戶機和伺服器應用程式,它們可以在本地網路上進行通訊,也可以通過 internet 在全球範圍內進行通訊。與其他 api 一...

socket效能優化 上

socket效能優化 上 2012年01月01日 b socket效能優化 b m.tim jones 資深軟體工程師,emulex 使用 sockets api,我們可以開發客戶機和伺服器應用程式,它們可以在本地網路上進行通訊,也可以通過 internet 在全球範圍內進行通訊。與其他 api 一...