2013-09-25 50 views
4

以前,當我使用干擾源的單生產者模式時,與單生產者模式相比,多生產者模式下lmax干擾者速度太慢

new Disruptor<ValueEvent>(ValueEvent.EVENT_FACTORY, 
     2048, moranContext.getThreadPoolExecutor(), ProducerType.Single, 
     new BlockingWaitStrategy()) 

表現還是不錯的。現在我處於多線程寫入單個環形緩衝區的情況。我發現ProducerType.Multi使代碼比單生產者模式慢數倍。這種糟糕的表現不會被我接受。所以我應該使用單一生產者模式,而多個線程調用帶有鎖的同一個事件發佈方法,那可以嗎?謝謝。

回答

1

恕我直言,多線程鎖定訪問單個生產者不會解決您的問題,因爲它只是將鎖定從干擾端轉移到您自己的程序。

問題的解決方案因您需要的事件模型的類型而異。即你是否需要事件按時間順序消耗;合併;或任何特殊要求。由於你在處理破壞者和多個生產者,這對我來說聽起來非常像外匯交易系統:-)無論如何,基於我的經驗,假設你需要每個生產者的時間順序,但不關心混合生產者之間的事件,我會建議你做一個隊列合併線程。該結構是

  • 每個生產者生產數據,並把它們放到自己的命名隊列
  • 工作線程不斷地檢查隊列。對於每個隊列,它將刪除一個或多個項目,並將其放到單個生產者干擾源的單個生產者中。

注意的是,在上述情況下,

  • 每個生產者隊列是一個生產者單個消費者隊列。
  • 破壞者是一個單一的生產者多消費者干擾者。
  • 取決於你的需要,爲了避免永久運行的線程,如果線程檢查了100個運行並且所有隊列都是空的,它可以設置一些變量並且等待(),並且事件生產者可以產生()它當看到它在等待。

我認爲這可以解決您的問題。如果不是,請張貼您對事件處理模式的需求,讓我們拭目以待。

+1

謝謝,亞歷克斯。你的建議聽起來很有希望。我想,Java'SynchronousQueue'可以用於這個目的。此外,我正在考慮另一種解決方案。我們可以使用0MQ爲每個生產者發送消息。對於單個接收方來說,線程不斷地輪詢生產者通道並且發送它通過干擾者獲得的任何消息。所以干擾者似乎贊成單一作家的原則...... :-) –

+0

是的。使用0MQ基本上是讓0MQ接收線程成爲「隊列合併」線程。如果你的系統現在已經在使用0MQ,那肯定夠用了。 –

+3

破壞者的原始動機之一是在收集框架中排隊的表現不佳。上面概述的設計同樣適用於使用多個干擾器而不是每個隊列。儘管取決於你的工作負載,但你可能會發現,只需添加一堆內存副本和上下文切換,只需一個多生產者就可以更快地處理多個隊列。 –

0

我對Disruptor有點新,但經過廣泛的測試和試驗後,我可以說ProducerType.MULTI對於2個或更多生產者線程更加準確和快速。

在MacBook上有14個生產者線程,即使我的測試代碼正在等待所有生產者結束(他們在10秒後運行),然後等待干擾者,ProducerType.SINGLE顯示更多發佈的消息事件結束。不太準確:這些額外發布的活動去哪裏了?

Driver start: PID=38619 Processors=8 RingBufferSize=1024 Connections=Reuse Publishers=14[SINGLE] Handlers=1[BLOCK] HandlerType=EventHandler<Event> 
    Done: elpased=10s eventsPublished=6956894 eventsProcessed=4954645 
    Stats: events/sec=494883.36 sec/event=0.0000 CPU=82.4% 

使用ProducerType.MULTI,更少的事件發表過單,但更多的事件實際消耗在同樣的10秒多單。並與MULTI,公佈事件的所有被消耗,這正是我所期望的,由於路上小心經過的時間到期後,司機自行關閉:

Driver start: PID=38625 Processors=8 RingBufferSize=1024 Connections=Reuse Publishers=14[MULTI] Handlers=1[BLOCK] HandlerType=EventHandler<Event> 
    Done: elpased=10s eventsPublished=6397109 eventsProcessed=6397109 
    Stats: events/sec=638906.33 sec/event=0.0000 CPU=30.1% 

還是那句話:2周或以上的生產者:使用ProducerType.MULTI。

順便說一句,每個Producer通過獲取下一個插槽,更新事件,然後發佈插槽,直接發佈到環形緩衝區。處理程序在調用onEvent方法時獲取事件。沒有額外的隊列。很簡單。