簡體   English   中英

linux在c ++中的線程之間傳遞高性能消息

[英]linux high performance message passing between threads in c++

說我有一個產生 2 個線程的進程

第一個線程在一個緊密循環中偵聽 UDP 端口上的數據包事件。 第二個線程是接收包含在這個 UDP 數據包中的字節並解析它/做一些事情。

誰能推薦一種比使用 linux 消息隊列更快的方法? 我認為它們很慢,因為它們在寫入隊列時復制字節並在從隊列中讀取時再次復制它們

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

我在想可能是內存中的環形緩沖區在線程和用於控制指向最近更新元素的指針之間共享的互斥鎖?

任何人的想法在這里?

我能想到的最有效的方法是使用一個鏈表、一個互斥鎖和一個條件變量:

  • 線程 A:

    1. 分配一個 udp-packet-buffer 對象(該對象應該包含previousnext指針,以及一個用於存儲 UDP 數據的字節數組)
    2. recv() UDP 數據到對象的字節數組
    3. 鎖定互斥鎖
    4. 將 udp-packet-buffer 對象附加到鏈表的尾部
    5. 解鎖互斥鎖
    6. 通知條件變量
    7. 轉到 1
  • 線程 B:

    1. 等待條件變量(直到條件變量發出信號)
    2. 鎖定互斥鎖
    3. 從鏈表的頭部彈出下一個 udp-packet-buffer
    4. 解鎖互斥鎖
    5. 解析/處理 udp-packet-buffer 對象中的 UDP 數據
    6. 刪除 udp-packet-buffer 對象
    7. 轉到 1

這為您提供了零拷貝通信機制。 持有互斥鎖所花費的時間很少,因此爭用也應該很低。

如果你想進一步優化,你可以讓線程 B 一次從鏈表中取出所有項目,而不是一次彈出一個——這在 O(1) 時間內是可能的帶有鏈表。 然后讓線程 A 僅在鏈接列表在附加其最新的 udp-packet-buffer 對象之前為空時才向條件變量發出信號。 這將減少線程在重負載下必須鎖定/解鎖/發出信號的次數。

這個非常好的答案也是我所期望的,當來到這個頁面時https://stackoverflow.com/a/8567548/2893944

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

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

結帳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

為了獲得最佳性能,您需要一個固定大小、無鎖、單寫入器、單讀取器的隊列。

這篇 codeproject 文章出現在一個快速的谷歌似乎合理並解釋了一些來龍去脈。

我不知道您的用例是什么 - 但如果采取如此冗長的措施 - 您的軟件(和環境)需要考慮如何處理由緩慢的消費者引起的隊列滿導致數據丟失的情況。

暫無
暫無

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

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