更多线程,更好的性能?

5 c++ winapi multithreading message-queue

当我写一个消息驱动的应用程序.就像标准的Windows应用程序一样,它广泛使用消息传递进行内部操作,这对于线程化的最佳方法是什么?

在我看来,基本上有三种方法(如果你有任何其他设置,请分享):

  1. 有一个线程处理所有消息.
  2. 为不同的消息类型(通用,UI,网络等)提供单独的线程
  3. 拥有多个共享和处理单个消息队列的线程.

那么,三者之间是否存在显着的性能差异?以下是一些一般性的想法:显然,最后两个选项受益于多个处理器的情况.另外,如果任何线程正在等待外部事件,则其他线程仍然可以处理不相关的消息.但忽略这一点,似乎多线程只增加开销(线程切换,更不用说更复杂的同步情况).

另一个问题:您是否建议在标准的Windows消息传递系统上实现这样的系统,或者实现单独的队列机制,为什么?

LBu*_*kin 8

线程模型的具体选择应该由您尝试解决的问题的性质驱动.设计这种应用程序的线程模型不一定有一种"正确"的方法.但是,如果我们采用以下假设:

  1. 消息频繁到达
  2. 消息是独立的,不会过分依赖共享资源
  3. 希望尽可能快地响应到达的消息
  4. 您希望应用程序在处理体系结构(即多码/多CPU系统)之间很好地扩展
  5. 可扩展性是关键的设计要求(例如,以更快的速度传递更多消息)
  6. 对线程故障/长操作的弹性是可取的

根据我的经验,最有效的线程架构是使用线程池.所有消息都到达单个队列,多个线程在队列上等待并在消息到达时处理消息.线程池实现可以为您拥有的所有三个线程分发示例建模.

#1单线程处理所有消息=>线程池只有一个线程

#N线程每N个消息类型=>具有N个线程的线程池,每个线程都会查看队列以查找适当的消息类型

#3所有消息的多个线程=>具有多个线程的线程池

此设计的好处是,您可以按照处理环境或消息负载的比例缩放线程中的线程数.线程数甚至可以在运行时扩展以适应所体验的实时消息负载.

大多数平台都有许多好的线程池库,包括.NET,C++/STL,Java等.

至于你的第二个问题,是否使用标准的Windows消息调度机制.这种机制带来了巨大的开销,实际上只用于通过Windows应用程序的UI循环来传送消息.除非这是你试图解决的问题,否则我建议不要将它用作一般的消息调度解决方案.此外,Windows消息携带的数据非常少 - 它不是基于对象的模型.每个Windows消息都有一个代码和一个32位参数.这可能不足以基于干净的消息传递模型.最后,Windows消息队列不是设计用于处理队列饱和,线程饥饿或消息重新排队等情况; 这些是在实施体面的消息排队解决方案时经常出现的情况.


Cha*_*tin 3

在不知道工作负载(即事件随时间的统计分布)的情况下,我们无法确定地告诉您很多信息,但总的来说

  • 具有多个服务器的单个队列至少同样快,而且通常更快,因此 1,3 比 2 更可取。
  • 大多数语言中的多线程会增加复杂性,因为需要避免争用和多写入器问题
  • 持续时间较长的进程可能会阻止处理其他可以更快完成的事情。

因此,马背上的猜测是,拥有一个事件队列,并且多个服务器线程将事件从队列中取出,可能会更快一点。

确保队列使用线程安全的数据结构。