要使用多少个线程?

Smu*_*202 14 c# multithreading .net-4.0 visual-studio-2010 threadpool

我知道有一些现存的问题,它们提供了很好的一般观点.我希望在C#/ VB.Net方面获得一些有关这些观点的实际实现(而不是哲学)的细节.

我的具体案例

我有一个WCF服务,除其他外,它接收文件.对于服务的大部分时间而言,这个特定区域实际上只是无所事事 - 当工作确实到来时,它会以极大不同的数量突然到达.

对于收到的每个文件(最多可以是每秒数千个),服务需要在1-10秒(每个)之间处理文件,具体取决于许多其他服务,本地资源和网络IO等待时间.

为了帮助这些突发工作负载的服务,我实现了一个队列系统.每秒收到的数千个文件被放置在队列中.控制器根据队列的大小计算要使用的线程数,直到达到"峰值最大线程数"设置,这将阻止它创建其他线程.这些线程放在线程池中,并重用于循环队列.控制器将; 每隔一段时间 重新计算所需的线程数.如果队列大小减小,则释放相关数量的线程.

这个古老的问题

我应该达到多少线程?很明显,每次收到一个文件时添加一个新的线程对于缺少一个更好的词来说是愚蠢的 - 性能最多会恶化.当每个核心的CPU利用率仅为10%时,限制线程,似乎也不是资源的最佳使用.

那么,有没有一种合适的方法来确定要限制的线程数?我希望服务可以通过对可用资源进行抽样来确定这一点,但这样做是否会影响性能?我知道常见的答案是监控工作负载,通过反复试验调整计数,直到找到我喜欢的数字,但由于此服务的性质(长时间闲置,然后是高/突发工作负载),可能需要很长时间是时候得到那种信息了.

那么,如果我们将服务器的图像移动到与第一个更快/更慢/不同的不同主机上呢?我必须重新重新整理过程吗?

理想情况下,我所追求的是协调员智能地增加线程池的大小,直到CPU利用率为x%(80%是合理的?90%?99%?).显然,我想这样做而不需要添加超过命中x%所需的线程,否则所有我最终都会遇到的不仅仅是等待IO资源,而是等待彼此.

提前致谢!


相关问题(如果您想要一些通用的想法):

要创建多少个线程?

有多少线程太多了?

要创建多少个线程以及何时创建?


给你带来并发症

如果我没有让问题变得更加困难,哪里会很有趣?

按照目前的情况,该服务在这些爆发期间定期达到100%cpu.问题是CPU利用率高峰.它从空闲(0-10%)变为100%,然后再次退回.我不确定我能帮到那个 - 理想情况下我不会把它全部带到100%.问题的存在是因为提到的文件实际上是图像,服务过程的一部分是将图像传递给System.Windows.Media黑盒,它为我做了一些复杂的图像处理.

由于IO等待和其他正在进行的处理,因此峰值之间存在间歇.如果达到100%的峰值无法帮助(我知道如何防止这种情况,或者我应该知道)我应该如何针对CPU利用率图表进行研究?经常坐在100%?弹跳在50-100之间?如果我确实通过抽样来确定哪些效果最好,那么是否可以保证切换虚拟服务器的主机在同一个图表中也能发挥最佳效果?

对于那些愿意回答的人,我不会考虑这种复杂性.随意忽略这一部分.然而,任何答案也解释了这种复杂性,甚至答案只是提供如何处理它的提示,我至少会upvote!

哎呀很长的问题 - 抱歉 - 并且感谢您的阅读!

Mar*_*mić 6

PerformanceCounter允许您查询处理器使用情况.

但是,您是否尝试过框架提供的功能?

        foreach (var file in files)
        {
            var workitem = file;
            Task.Factory.StartNew(() =>
            {
                // do work on workitem
            }, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
        }
Run Code Online (Sandbox Code Playgroud)

您可以在任务中调整任务的并发级别.工厂.

默认情况下,.NET 4线程池将调度它在运行它的硬件上最常执行的线程数,但您可以更改以前链接的工作方式.

您可能需要一个自定义解决方案,但可以使用标准对您进行基准测试.

编辑:(评论说明):

不需要链接,我可能使用了一个发明的术语,因为英语不是我的语言.我的意思是:有一个变量用于存储最后一次检查之前的差异(prevDelta),并将其称为delta.每次"检查"时,将其添加到变量avrageDelta并除以2.你将拥有变量averageDelta,因为你没有任何活动,所以变量很大.然后有另一组delta变量,一个你已经(delta - prevdelta),并将它存储在一个delta变量中,该变量不是所有增量的平均值,而是在很短的时间内的delta的平均值(你必须得出一个准确计算这个时间方差的算法.完成此操作后,您可以比较平均增量和"时间增量".平均三角洲将大部分低,并且会随着爆发而缓慢上升.在同一时期,时间差异将会非常快.然后你就会遇到爆发停止的情况,平均增量缓慢下降,"时间"变得非常快.