线程 - 消息传递

时间:2012-01-02 14:47:16

标签: multithreading message-passing

我试图找到一些资源以获得最佳性能并通过消息传递进行扩展。我听说通过值而不是引用传递的消息可以是更好的可伸缩性,因为它适用于NUMA样式设置并减少了对给定内存地址的争用。

我认为基于值的消息传递仅适用于“较小”的消息。将“较小”定义为什么?在什么时候参考会更好?会以这种方式进行流处理吗?

我正在为这些问题寻找一些有用的提示或资源。

谢谢: - )

P.S。我在C#工作,但我认为这对于这些设计问题并不重要。

2 个答案:

答案 0 :(得分:3)

一些因素可以补充杰里米的出色建议:

1)按值传递仅对小消息有效。如果数据在开始时具有[cache-line-size]未使用区域以避免错误共享,那么您已经接近通过引用传递更有效的大小。

2)更宽的队列意味着队列占用更多空间,影响内存使用。

3)将数据复制到宽队列结构中/从宽队列结构中复制数据需要时间。除了在移动数据时实际使用CPU,队列在复制期间保持锁定状态。这会增加队列上的争用,并导致与队列宽度相关的整体性能损失。如果您的代码中存在任何死锁潜力,那么长时间保持锁定将无济于事。

4)按值传递往往会导致特定于数据大小的代码,即。在编译时修复。除了令人讨厌的模板侵扰之外,这使得在运行时调整缓冲区大小等非常困难。

5)如果消息通过引用和malloced / freed / newed / dispos / GC'd传递,这可能导致内存管理器上的过度争用以及频繁,浪费的GC。我通常使用在启动时分配的固定消息池,特别是为了避免这种情况。

6)当通过引用传递时,处理字节流可能很尴尬。如果字节流的特征在于频繁传递单个字节,则只有字节被分块时,传递引用才是明智的。这可能导致需要超时以确保及时地将部分填充的消息分派到下一个线程。这引入了复杂性和延迟。

7)传递参考设计本身更容易泄漏。这可能导致延长测试时间和valgrind过量 - 这是一种特别痛苦的成瘾,(我使用固定大小的消息对象池的另一个原因)。

8)复杂的消息,例如。包含对其他对象的引用的那些,如果按值传递,可能会导致所有权和生命周期管理的可怕问题。示例 - 服务器套接字对象具有对缓冲区列表对象的引用,该对象包含不同大小的缓冲区实例数组(来自IOCP服务器的实例)。尝试按值传递..

9)许多操作系统调用除了指针外无法处理任何操作。你不能PostMessage,(这是一个Windows API,对于所有你快乐的脚),即使是一个256字节的结构值,一个调用(你只有2个wParam,lParam整数)。设置异步回调的调用通常允许将“上下文数据”发送到回调 - 几乎总是只有一个指针。任何将要使用此类操作系统功能的应用程序几乎都被迫通过引用传递。

答案 1 :(得分:0)

Jeremy Friesner的评论似乎是最好的,因为这是一个新领域,尽管Martin James的观点也很好。我知道微软正在研究未来内核的消息传递,因为我们获得了更多内核。

似乎有一个框架可以处理消息传递,并声称它具有比当前.Net生产者/消费者泛型更好的性能。我不确定它与4.5的.Net数据流的比较

https://github.com/odeheurles/Disruptor-net