11

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

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

在破坏者 DSL 术语中,设置如下所示:

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

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

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

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

有一个额外的消费者: 随着额外的消费者

图中这个灰色部分是什么?它来自哪里?我想它与线程同步有关,但我在任务控制中找不到任何其他统计数据可以表明任何此类延迟或争用。

4

2 回答 2

3

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

来自(强调我的)的API 文档EventHandlerGroup<T>.then

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

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

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

事件漏斗

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

于 2015-02-20T15:17:02.863 回答
2

根据您所展示的内容,我可以在这里看到两种可能性。您可能会受到其中之一或两者的影响,我建议同时测试两者。1)IO处理瓶颈。2) 写入缓冲区的多个线程争用。

IO处理

从显示的数据中,您已经声明,一旦启用 IO 组件,您的吞吐量就会降低,内核时间会增加。这很可能是您的消费者线程正在写入时的 IO 等待时间。执行write()调用的上下文切换比什么都不做要昂贵得多。你Decoder的 s 现在被限制在消费者的最大速度上。要检验这个假设,您可以删除write()呼叫。换句话说,打开输出文件,准备输出字符串,而不是发出写入调用。

建议

  • 尝试删除write()消费者中的调用,看看它是否减少了内核时间。
  • 您是否按顺序写入单个平面文件 - 如果没有,试试这个
  • 您是否使用智能批处理(即:缓冲直到endOfBatch标志,然后在单个批处理中写入)以确保尽可能有效地捆绑 IO?

对多个作家的争用

根据您的描述,我怀疑您Decoder的 s 正在从中断器中读取,然后写回同一个缓冲区。这将导致多个写入器的问题,即 CPU 写入内存的争用。我建议的一件事是有两个干扰环:

  1. Producer写入#1
  2. Decoder从 #1 读取,执行 RS 解码并将结果写入 #2
  3. Consumer从 #2 读取,并写入磁盘

假设您的 RB 足够大,这应该会导致良好的干净遍历内存。

这里的关键是不要让Decoder线程(可能在不同的内核上运行)写入刚刚由Producer. 只有 2 个内核执行此操作,您可能会看到吞吐量有所提高,除非磁盘速度是瓶颈。

我在这里有一篇博客文章,其中更详细地描述了如何实现这一点,包括示例代码。http://fasterjava.blogspot.com.au/2013/04/disruptor-example-udp-echo-service-with.html

其他想法

  • WaitStrategy了解您正在使用什么、机器中有多少物理 CPU 等也会很有帮助。
  • WaitStrategy考虑到最大的延迟将是 IO 写入,您应该能够通过移动到不同的位置来显着降低 CPU 利用率。
  • 假设您使用的是相当新的硬件,您应该能够仅使用此设置使 IO 设备饱和。
  • 您还需要确保文件位于不同的物理设备上以实现合理的性能。
于 2015-02-24T12:01:52.150 回答