Concurrency 何时使用中断器模式,何时使用本地存储和工作窃取?
以下是正确的吗Concurrency 何时使用中断器模式,何时使用本地存储和工作窃取?,concurrency,concurrent-programming,disruptor-pattern,work-stealing,Concurrency,Concurrent Programming,Disruptor Pattern,Work Stealing,以下是正确的吗 如果必须以多种方式(io操作或注释)处理每个条目,则具有更好的并行性能和可伸缩性,因为可以使用多个使用者并行处理,而不会产生争用 相反,(即本地存储条目并从其他线程窃取条目)如果每个条目只能以单一方式处理,则具有更好的并行性能和可伸缩性,因为在中断器模式中将条目分散到多个线程上会导致争用 (当涉及多个生产者时,破坏者模式是否比其他无锁多生产者多消费者队列(例如)快得多?) 我的详细情况: 处理一个条目会产生几个新条目,这些条目最终也必须被处理。性能具有最高优先级,按FIFO
- 如果必须以多种方式(io操作或注释)处理每个条目,则具有更好的并行性能和可伸缩性,因为可以使用多个使用者并行处理,而不会产生争用
- 相反,(即本地存储条目并从其他线程窃取条目)如果每个条目只能以单一方式处理,则具有更好的并行性能和可伸缩性,因为在中断器模式中将条目分散到多个线程上会导致争用
我的详细情况: 处理一个条目会产生几个新条目,这些条目最终也必须被处理。性能具有最高优先级,按FIFO顺序处理的条目具有第二优先级 在当前的实现中,每个线程使用一个本地FIFO,并在其中添加新的条目。空闲线程从其他线程的本地FIFO窃取工作。线程处理之间的依赖关系使用无锁哈希表(CASs on write,具有桶粒度)来解决。这会导致相当低的争用,但FIFO顺序有时会被打破 使用中断器模式将保证FIFO顺序。但是,将条目分发到线程上是否会导致比本地FIFO更高的争用(例如,读取游标上的CAS)以及工作窃取(每个线程的吞吐量大致相同)
我找到的参考资料 (第5+6章)中的性能测试不包括不相交的工作分配 是我找到的唯一关于干扰者+工作盗窃的参考资料。它指出,如果存在任何共享状态,则每个线程的队列速度会显著降低,但没有详细说明或解释原因。我怀疑这句话是否适用于我的情况:
- 使用无锁哈希表解析共享状态李>
- 必须在消费者之间分散分配条目李>
- 除了工作窃取之外,每个线程只在其本地队列中读写
- 当您的实施以信息为中心时,请使用工作窃取。每个线程都可以拾取一条消息并运行它直到完成。对于示例HTTP服务器,每个入站HTTP请求分配一个线程。该线程专注于处理从开始到结束的请求—记录请求、检查安全控制、执行vhost查找、获取文件、发送响应和关闭连接
- 当您的实施以任务为重点时,请使用中断器。每个线程都可以在特定的处理阶段工作。备选示例:对于任务焦点,处理将分为几个阶段,因此您将有一个执行日志记录的线程、一个用于安全控制的线程、一个用于vhost查找的线程,等等;每个线程专注于自己的任务,并将请求传递给管道中的下一个线程。阶段可能是并行的,但总体结构是一个专注于特定任务的线程,并在线程之间传递消息
- Disruptor-在需要严格的阶段顺序时非常有用,在所有任务长度一致时具有额外的好处,例如:外部系统上没有阻塞,每个任务的处理量非常相似。在这个场景中,您可以假设所有线程都将在系统中均匀地工作,因此每处理N条消息就安排N个线程。我喜欢将Disruptor看作是实现SEDA类系统的一种有效方法,其中线程处理阶段。当然,您可以有一个应用程序,其中一个阶段和多个并行单元在每个阶段执行相同的工作,但在我看来,这并不是真正的观点。这将完全避免共享状态的成本
- 工作窃取-当任务的持续时间不同且消息处理顺序不重要时,使用此选项,因为这允许空闲且已消耗其消息的线程继续从另一个任务队列进行处理。这样,例如,如果您有10个线程,1个线程在IO上被阻塞,其余线程仍将完成其处理