2011-12-19 23 views
1

說我有其派生2個線程linux的高性能消息線程之間通過在C++

第一線程在緊湊循環中對UDP端口上的分組事件偵聽的方法。 第二個線程是接收這個UDP包中包含的字節並解析它/做的東西。

任何人都可以推薦比使用linux消息隊列更快的方法嗎? 我認爲它們很慢,因爲它們在寫入隊列時複製字節,並在隊列中讀取時再次複製它們

我意識到了zeromq庫,但是有沒有這種方法可以在沒有這種開銷的情況下做到這一點? 我意識到我可以在兩個線程之間使用tcp/ip套接字進行簡單的排隊通信,但有沒有更快的方法?

我想也許是在線程和互斥量之間共享的內存環形緩衝區用於控制指針最近更新的元素?

anyones想法嗎?

+2

這真的是你的瓶頸?爲什麼不在線程中使用共享內存,而不是在進程中使用共享內存? – Flexo 2011-12-19 20:37:24

+5

你還試過了什麼? Unix套接字?管? SysV IPC? – fge 2011-12-19 20:37:55

+0

看看http://code.google.com/p/disruptor/:它是java,但是,它可能會激勵你......;) – Nim 2011-12-19 20:39:12

回答

5

,我能想到的會使用一個鏈表,一個互斥體的最有效方法,並且一個條件變量:

Thread A: 
    1. Allocate a udp-packet-buffer object (the object should contain 'previous' and 'next' pointers, and an array of bytes to store UDP data in) 
    2. recv() UDP data into the object's byte-array 
    3. lock the mutex 
    4. append the udp-packet-buffer object to tail of the linked-list 
    5. unlock the mutex 
    6. signal the condition variable 
    7. goto 1 

Thread B: 
    1. wait on the condition variable (until the condition variable is signaled) 
    2. lock the mutex 
    3. pop the next udp-packet-buffer off the head of the linked-list 
    4. unlock the mutex 
    5. parse/handle the UDP data in the udp-packet-buffer object 
    6. delete the udp-packet-buffer object 
    7. goto 1 

這就給了你一個零拷貝通信機制。花在互斥量上的時間很少,因此爭用也應該很低。

如果你想進一步優化,你可以讓線程B一次抓取鏈表中的所有項目,而不是一次只彈出一個項目 - 在O中可以做的事情(1)帶有鏈表的時間。然後讓線程A發信號通知條件變量,只有當鏈接列表在其附加最新的udp-packet-buffer對象之前是空的。這將減少線程在重負載時鎖定/解鎖/信號的次數。

+0

這個答案是我想要的;條件變量的不錯用法,因爲我認爲使用條件變量比互斥鎖的輪詢更好 – 2011-12-20 14:44:03

0

結帳http://www.boost.org/libs/circular_buffer/ 我使用填充boost :: array < 1500>作爲一個項目中的2個線程之間的通信點,我看不出它在任何方面都很慢。第一個線程正在接受UDP包,並通過檢查一些位來快速檢查它是否應將其放入緩衝區。它可以複製和複製,但即使在我配置文件時也不會顯示。

編輯:BoundedBuffer例子是有趣的一點http://www.boost.org/libs/circular_buffer/doc/circular_buffer.html#boundedbuffer

0

爲了獲得最大的性能,你需要一個固定的大小,lockess,單作家,單閱讀器隊列。

This codeproject article出現在一個快速的谷歌似乎是合理的,並解釋了一些來龍去脈。

我不知道你的用例是什麼 - 但是如果採取這樣一個冗長的措施 - 你的軟件(和環境)需要考慮如何處理緩慢的消費者引起的完全隊列會導致數據丟失的情況。

+0

我不認爲術語「最大性能」在此適用。這可能是最低的延遲(當然有單線程的情況除外),但對於掛鉤CPU的價格。如果可以接受,取決於情況,但我不會稱之爲「最高性能」。 – Slava 2015-06-30 14:49:15

1

這很好的答案是我預期的那樣好,來到這個頁面的時候 https://stackoverflow.com/a/8567548/2893944

一個小小的音符,可能會有所幫助:擺脫動態內存分配也是一個點,可以提高性能和避免內存碎片(例如:使用靜態數組,使用內存池)。

(這應該是一個評論,但沒有足夠的聲譽)