是什么导致这种性能下降?

Zol*_*tán 11 java performance multithreading disruptor-pattern

我正在使用Disruptor框架对某些数据执行快速Reed-Solomon纠错.这是我的设置:

          RS Decoder 1
        /             \
Producer-     ...     - Consumer
        \             /
          RS Decoder 8 
Run Code Online (Sandbox Code Playgroud)
  • 生产者从磁盘读取2064字节的块到字节缓冲区.
  • 8个RS解码器消费者并行执行Reed-Solomon纠错.
  • 消费者将文件写入磁盘.

在disruptor DSL术语中,设置如下所示:

        RsFrameEventHandler[] rsWorkers = new RsFrameEventHandler[numRsWorkers];
        for (int i = 0; i < numRsWorkers; i++) {
            rsWorkers[i] = new RsFrameEventHandler(numRsWorkers, i);
        }
        disruptor.handleEventsWith(rsWorkers)
                .then(writerHandler);
Run Code Online (Sandbox Code Playgroud)

当我没有磁盘输出消费者(没有.then(writerHandler)部分)时,测量的吞吐量是80 M/s,一旦我添加消费者,即使它写入/dev/null,甚至不写,但它被声明为依赖消费者,性能下降到50-65 M/s.

我已经使用Oracle Mission Control对其进行了分析,这就是CPU使用率图表显示的内容:

没有额外的消费者: 没有额外的消费者

另外一个消费者: 有额外的消费者

图中的灰色部分是什么?它来自何处?我想它与线程同步有关,但我在Mission Control中找不到任何其他统计信息来指示任何此类延迟或争用.

dur*_*597 3

你的假设是正确的,这是一个线程同步问题。

来自API 文档EventHandlerGroup<T>.then(重点是我的)

设置批处理程序以使用环形缓冲区中的事件。这些处理程序仅在该组中的每个 处理程序处理完事件后才会处理事件EventProcessor

此方法通常用作链的一部分。例如,如果处理程序 A 必须在处理程序 B 之前处理事件:

这必然会降低吞吐量。把它想象成一个漏斗:

事件漏斗

消费者必须等待每个EventProcessor都完成,然后才能继续通过瓶颈。