我可能会做错这一切,但这是我的问题和建议的解决方案:
您有一个 50+ GB 的文件,其中包含数亿条需要非常快速处理的独立记录。我目前的解决方案是每小时获得 7400 万条记录。我为 I/O 线程使用了一个阻塞队列,每个工作线程都试图从这个队列中获取数据块。
由于 I/O 和工作线程之间的互斥争用,上述内容非常缓慢。
有没有办法在没有锁的情况下做这种风格的生产者/消费者?
我可能会做错这一切,但这是我的问题和建议的解决方案:
您有一个 50+ GB 的文件,其中包含数亿条需要非常快速处理的独立记录。我目前的解决方案是每小时获得 7400 万条记录。我为 I/O 线程使用了一个阻塞队列,每个工作线程都试图从这个队列中获取数据块。
由于 I/O 和工作线程之间的互斥争用,上述内容非常缓慢。
有没有办法在没有锁的情况下做这种风格的生产者/消费者?
与其使用阻塞队列并让工作线程从中拉出,不如给每个线程一个自己的队列,让 I/O 线程将批量工作推送到每个线程的队列中。
假设您不介意付出额外的努力来实现某种方式来跟踪可以将多少项目推入每个队列,则循环队列对此非常有用;如果 I/O 线程读取新记录的速度快于工作线程处理它们的速度,则必须小心不要覆盖未处理的记录。
确保记录不被覆盖的一种方法是让工作线程每隔一段时间发送一条消息以更新 I/O 线程已处理的记录数量。这种方法不需要锁定;只是每隔一段时间更新 I/O 线程的原子操作。
除此之外,您还可以通过在将最后一批推入队列时使用非阻塞 I/O 读取更多记录来获得更好的性能。它还有助于了解瓶颈是磁盘访问还是处理。
单个读取器线程将可用大小的块放入消费者访问的队列中怎么样?或者让消费者将他们自己的 ID 放入一个队列中,文件阅读器每次读取另一个块时都会从该队列中提取。后者可能不会经常阻止读者。
存在单生产者单消费者 (SPSC) 无锁队列。由此,您可以让生产者线程以循环方式(每个工人一个队列)将工作分派给每个工人。请注意,某些队列可能已满,在这种情况下(对于这一轮)忽略它们。
关于 IO:你真的可以分割文件吗?如果您有一种廉价的方法来检测记录的结尾,那么拆分文件并将各个部分放在不同的机器上可能很简单。或者只是购买更快的硬盘。