2011-07-28 60 views
4

我們有一個「發佈者」應用程序,它使用多播發送數據。該應用程序對性能非常敏感(我們正在微秒級別進行優化)。監聽此發佈數據的應用程序可以(並且通常)與發佈應用程序在同一臺機器上。Linux多播sendto()性能隨本地監聽器而下降

我們最近注意到一個有趣的現象:執行sendto()的時間與機器上監聽器的數量成比例地增加。

例如,假設沒有監聽器,sendto()調用的基準時間爲5微秒。每個額外的偵聽器將sendto()調用的時間增加約2微秒。因此,如果我們有10個監聽器,那麼sendto()調用需要2 * 10 + 5 = 25微秒。

這對我來說建議sendto()調用會阻塞,直到數據被複制到每個單個監聽器。

分析方也支持這一點。如果有10個監聽器,則每個監聽器都比前一個時間晚兩微秒接收數據。 (即,第一個監聽獲得的數據在約五微秒,最後聽者獲得約23--25毫秒的數據。)

有什麼辦法,無論是在計劃層面還是制度層面改變這種行爲?類似於非阻塞/異步sendto()調用?或者至少阻止,直到消息被複制到內核的內存中,所以它可以在不等待所有偵聽器的情況下返回)?

+0

唯一的行爲是阻塞直到內存被複制到內核空間SKB中。零拷貝只能通過Wireshark&'tcpdump'使用的較低PF_PACKET接口實現。 –

+0

你機器上的路線是什麼?特別是,您是否爲多播組或整個224.0.0.0/4塊設置了路由? –

回答

0

多點傳送循環非常低效,不應用於高性能消息傳遞。正如您在每次發送時注意到的那樣,內核正在將消息複製到每個本地監聽器。

推薦的方法是使用單獨的IPC方法分發到同一主機上的其他線程和進程,共享內存或unix套接字。

例如,通過在同一個ZeroMQ套接字上的PGM多播連接上面添加IPC連接,可以使用ZeroMQ套接字輕鬆實現此功能。

+0

另外,Matt的團隊可以投入時間來解決內核與當地聽衆的性能問題。 –

+0

@Zan正確,但我認爲內核中的選項相對於[LMAX的干擾程序](http://code.google.com/p/disruptor/)等零拷貝用戶空間方法相當有限。 –

+0

如果端口非阻塞,爲什麼會發送阻塞?複製發生一次到內核緩衝區 –

0

對不起,請問顯而易見,但是是套接字非阻塞? (將O_NONBLOCK添加到端口的標記集合 - 請參見fcntl

+0

嘗試過,但似乎沒有任何區別。發送線程仍然「阻塞」,直到所有接收器完全收到數據。 – Matt