分析/优化大量多线程应用程序

Kie*_*one 7 .net c# multithreading

我正在编写一个性能关键的.NET应用程序,它大量使用多线程.

使用Visual Studio性能分析器,使用Exclusive样本的顶级函数是:

WaitHandle.WaitAny() - 14.23%

@JIT_MonReliableEnter@8 - 7.76%

Monitor.Enter - 5.09%

基本上,我的前3个函数正在使用线程原语,并且在某种程度上我不相信.相比之下,我的工作/处理程序非常小,我正在努力提高性能.我相信所涉及的算法非常合理,尽管我经常审查它们.

我的问题是:

  • 如果这些方法中有14.23%的CPU样本 - 对于大多数样本来说CPU是否有效'空闲',即只等待其他线程?或者是线程的空闲部分 - 等待未显示为配置文件跟踪的一部分[并且这些同步方法中所有开销的总和中的27.08%]?(我可以猜测这大部分都是空闲的,但请欣赏一些体面的参考资料,请回答这个问题)
  • 我已经审查了我的锁定方案,但这些结果是否表明我应该考虑进一步优化的一些特定瓶颈或技术?
  • WaitAny特别是很穷?我大量使用它来检查特定队列对象是否可读/可写,还同时检查中止标志.有没有更好的方法呢?

Jim*_*hel 5

WaitHandle.WaitAny当线程位于 a或 a时,您的 CPU 不一定空闲Monitor.Enter。处于等待状态的线程处于空闲状态,但可能其他线程正忙于执行。对于 来说尤其如此Monitor.Enter。如果一个线程被锁阻塞,那么人们会希望拥有该锁的线程正在执行代码而不是闲置。

另外,如果您的线程使用WaitAny从队列中读取数据,那么队列中可能根本没有任何内容。对于消费者代码来说,这不是性能问题。这只是意味着生产者没有足够快地将东西放入队列中。现在,这可能是因为生产者速度很慢,或者因为数据传入的速度不够快。

如果您处理数据的速度比数据输入的速度快,那么看起来您并不存在性能问题。当然不是在消费者方面。

至于用于WaitAny排队,我建议您使用BlockingCollection和采用取消令牌的方法,例如TryAdd(T, Int32, CancellationToken)。转换为取消令牌确实简化了我的多线程排队代码。