4

以前,当我使用破坏者的单生产者模式时,例如

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

性能很好。现在我处于多个线程将写入单个环形缓冲区的情况。我发现这ProducerType.Multi使代码比单生产者模式慢几倍。我不会接受这种糟糕的表现。那么我应该使用单生产者模式,而多个线程使用锁调用相同的事件发布方法,可以吗?谢谢。

4

2 回答 2

3

我对 Disruptor 有点陌生,但经过广泛的测试和试验,我可以说 ProducerType.MULTI 对于 2 个或更多生产者线程更准确、更快。

在 MacBook 上有 14 个生产者线程时,ProducerType.SINGLE 显示已发布的事件多于消耗的事件,即使我的测试代码正在等待所有生产者结束(它们在 10 秒运行后执行),然后等待破坏者结束。不太准确:那些额外发布的事件去哪儿了?

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,发布的事件比使用 SINGLE 少,但实际上在 10 秒内消耗的事件比使用 SINGLE 的要多。使用 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 通过获取下一个 slot,更新事件,然后发布 slot,直接发布到 ring buffer。每当调用其 onEvent 方法时,处理程序都会获取事件。没有额外的队列。很简单。

于 2013-11-21T21:14:02.847 回答
1

恕我直言,由带锁的多线程访问的单个生产者不会解决您的问题,因为它只是将锁定从破坏者端转移到您自己的程序。

您的问题的解决方案因您需要的事件模型类型而异。即您是否需要按时间顺序消费事件;合并;或任何特殊要求。由于您正在与破坏者和多生产者打交道,这对我来说听起来很像外汇交易系统:-) 无论如何,根据我的经验,假设您需要每个生产者的时间顺序但不关心生产者之间的混合事件,我会建议你做一个队列合并线程。结构是

  • 每个生产者产生数据并将它们放入自己的命名队列
  • 工作线程不断检查队列。对于每个队列,它会删除一个或多个项目并将其放入单个生产者破坏者的单个生产者。

请注意,在上述场景中,

  • 每个生产者队列是单个生产者单个消费者队列。
  • 破坏者是单一生产者多消费者破坏者。
  • 取决于你的需要,为了避免一个永远运行的线程,如果线程检查,比如说,100 次运行并且所有队列都是空的,它可以设置一些变量并去 wait() 并且事件生产者可以在看到它时 yield() 它等待。

我认为这可以解决您的问题。如果没有,请发布您对事件处理模式的需求,让我们看看。

于 2013-09-26T08:54:00.167 回答