簡體   English   中英

召喚緩慢的原因

[英]Reasons for a slow recv call

我正在編寫兩個應用程序(在C中),這些應用程序進行多次發送和接收調用(例如,我正在實現遠程文件復制)。

我總是發送一個64字節的標題,其中包含以下消息正文的長度和一些其他信息。

在一些文件上測試我的應用程序時,我發現一些recv調用需要很長時間才能完成(大約40 毫秒 )。 使用strace我發現它首先發送一個377字節的消息體(在這種情況下它是我要復制的文件的全部內容)。

服務器應用程序開始發送消息體,大約需要48 us 現在客戶端應用程序消耗大約38 毫秒來接收這些字節。

從那時起,每個接收呼叫消耗這么多時間,因為它們每個都在接收中阻塞並等待回復。

服務器的strace

[pid 27158] 1292236124.465827發送(6,“\\ 0 \\ 0 \\ 1 \\ 271 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0core.fwrite \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0“...,64,0)= 64 <0.000031>

[pid 27158] 1292236124.466074發送(6,“\\ 0 \\ 0 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 10 \\ 0 \\ 0 \\ 0 \\ 0 \\ 1 \\ \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0“......,377,0)= 377 <0.000048>

客戶的strace

[pid 27159] 1292236124.466364 recv(4,“\\ 0 \\ 0 \\ 1 \\ 271 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0core.fwrite \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0“...,64,0)= 64 <0.000027>

[pid 27159] 1292236124.466597 recv(4,“\\ 0 \\ 0 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 10 \\ 0 \\ 0 \\ 0 \\ 0 \\ 1 \\ 1 \\ \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0“......,377,0)= 377 <0.037456>

這個問題確實給我帶來了困難,因為我不明白為什么客戶端上的接收呼叫花了這么多時間。

任何提示都將受到高度贊賞。

聽起來像Nagle的算法對我來說。 你沒有提交足夠的數據,所以它會延遲一段時間,以防有更多的數據出現。 您可以通過套接字選項禁用它,然后重試。

是的,這肯定是Nagle的算法。我建議您閱讀它,因為如果您發送大塊數據,它應該在它有“大量”數據時立即發送。 沒有自己閱讀,我不完全確定“很多”是多少,但它可能是可配置的。

但是,如果您為每個連接執行一個文件,那么如果您一次性發送標題和內容,那么您應該不會遇到小文件問題 - 無論如何您應該這樣做以提高吞吐量。 正如李傑所說(或多或少)“吞吐量是游戲的名稱”。 您需要將文件數據與標頭一起緩沖。 這是我可能會推薦多線程的少數情況之一 - 一個線程從文件填充緩沖區,另一個線程從緩沖區加載套接字。 您需要使用互斥鎖保護緩沖區和關聯變量,我也建議使用條件變量。 文件讀取線程在添加了更多數據時發出信號,並在緩沖區已滿時等待,並且套接字寫入線程在讀取時發出信號並在緩沖區為空時等待。 寫入64字節標題后,文件讀取線程不應發出信號。 讓它首先加載完整的數據緩沖區。

您也可以嘗試使用兩個緩沖區並使用它們來減少互斥鎖定延遲。 如果你做對了,文件讀取線程將寫入緩沖區A,而套接字寫入線程正在讀取緩沖區B,反之亦然,線程將更少地等待互斥鎖。

即使采用這樣的策略,仍然值得禁用Nagle的算法。 除了形成任何東西,如果您的代碼被設計為無論如何都要避免大量的小數據包,那么Nagle的算法是多余的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM