简体   繁体   English

要使用多少个线程?

[英]How many threads to use?

I know there are some existing questions and they provide a very good general perspective on things.我知道存在一些现有的问题,它们为事物提供了一个非常好的一般观点。 I'm hoping to get some details on the C#/VB.Net side for the actual implementation (not philosophy) of some of these perspectives.我希望在 C#/VB.Net 方面获得一些细节,以了解其中一些观点的实际实现(而不是哲学)。

My Particular Case我的特殊情况

I have a WCF Service which, amongst other things, receives files.我有一个 WCF 服务,其中包括接收文件。 For most of the service's life this particular area is actually just sat doing nothing - when work does come it arrives in high bursts of greatly varying quantities.在服务生命周期的大部分时间里,这个特定区域实际上只是坐着无所事事——当工作确实到来时,它会以大量不同的数量大量涌入。

For each file received (which at a max can be thousands per second) the service needs to work on the files for between 1-10 seconds (each) depending on a number of other services, local resources, and network IO wait times.对于收到的每个文件(每秒最多数千个),服务需要在文件上工作 1-10 秒(每个),具体取决于许多其他服务、本地资源和网络 IO 等待时间。

To aid the service with these burst workloads I implemented a Queue system.为了帮助服务处理这些突发工作负载,我实施了一个队列系统。 Those thousands of files recieved per second are placed onto the Queue.每秒接收的数千个文件被放置到队列中。 A controller calculates the number of threads to use based on the size of the queue, up until it reaches a "Peak Max Threads" setting which prevents it from creating additional threads. controller 根据队列的大小计算要使用的线程数,直到达到阻止它创建额外线程的“Peak Max Threads”设置。 These threads are placed in a thread pool, and reused to cycle through the queue.这些线程被放置在一个线程池中,并在队列中循环使用。 The controller will; controller 将; at intervals;每隔一段时间; recalculate the number of threads required.重新计算所需的线程数。 If the queue size reduces, a relevant number of threads are released.如果队列大小减小,则释放相关数量的线程。

The age old problem古老的问题

How many threads should I peak at?我应该在多少线程上达到峰值 Clearly, adding a new thread everytime a file was received would be silly for lack of a better word - the performance, at best, would deteriorate.显然,每次收到文件时添加一个新线程是愚蠢的,因为没有更好的词——性能,充其量只会恶化。 Capping the threads when CPU utilization is only 10% across each core, also doesn't seem to be the best use of resources.当每个内核的 CPU 利用率仅为 10% 时限制线程,似乎也不是对资源的最佳利用。

So, is there an appropriate way to determine how many threads to cap at?那么,是否有适当的方法来确定要限制多少线程? I would rather the service could determine this for itself by sampling available resources, but is there a performance hit from doing so?我宁愿服务可以通过对可用资源进行采样来自行确定这一点,但是这样做会影响性能吗? I know the common answer is to monitor workloads, adjust the counts through trial and error until I find a number I like, but due to the nature of this service (long periods of idle followed by high/burst workloads) it could take a long time to get that kind of information.我知道常见的答案是监控工作负载,通过反复试验调整计数,直到找到我喜欢的数字,但由于此服务的性质(长时间空闲,然后是高/突发工作负载),它可能需要很长时间是时候获取此类信息了。

What then if we move the server's image to a different host which is faster/slower/different to the first?那么如果我们将服务器的镜像移动到另一个更快/更慢/不同的主机上呢? I have to re-sample the process all over again?我必须重新采样整个过程吗?

Ideally what I'm after, is for the co-ordinator to intelligently increase the size of the threadpool until CPU utilisation is at x% (would 80% be reasonable? 90%? 99%?).理想情况下,我所追求的是协调者智能地增加线程池的大小,直到 CPU 利用率达到 x%(80% 是否合理?90%?99%?)。 Clearly, I want to do this without adding more threads than is necessary to hit x% otherwise all I'll end up with is threads not just waiting on IO resources, but awaiting each other too.显然,我希望在不添加超过达到 x% 所需的线程数的情况下执行此操作,否则我最终会得到的线程不仅是在等待 IO 资源,而且还相互等待。

Thanks in advance!提前致谢!


Related questions (if you want some generic ideas):相关问题(如果您想要一些通用的想法):

How many threads to create? 要创建多少个线程?

How many threads is too many?多少个线程太多了?

How many threads to create and when? 创建多少线程以及何时创建?


A Complication for you给你的并发症

Where would be the fun if I didn't make the problem more difficult?如果我不让问题变得更困难,那还有什么乐趣呢?

As it currently stands, the service does hit 100% cpu during these bursts, regularly.就目前而言,该服务在这些突发期间确实会定期达到 100% 的 cpu。 The issue is the CPU utilisation spikes.问题是 CPU 利用率峰值。 It goes from idle (0-10%) to 100%, and back down again.它从空闲 (0-10%) 变为 100%,然后再次下降。 I'm not sure I can help that - ideally I wouldn't take it all the way to 100%.我不确定我能帮上忙——理想情况下,我不会一直做到 100%。 The problem exists because the files mentioned are in fact images, and part of the services' process is to pass the image through to the System.Windows.Media blackbox which does some complex image processing for me.存在问题是因为提到的文件实际上是图像,并且服务的一部分过程是将图像传递给 System.Windows.Media 黑盒,它为我做了一些复杂的图像处理。

There are then lulls in between the spikes because of the IO waits and other processing that goes on.由于 IO 等待和其他处理正在进行,因此在尖峰之间会出现停顿。 If the spikes hitting 100% can't be helped (and I'm all for knowing how to prevent that, or if I should) how should I aim for the CPU utilisation graph to look?如果无法帮助达到 100% 的峰值(我完全知道如何防止这种情况发生,或者如果我应该这样做),我应该如何瞄准 CPU 利用率图? Sat constantly at 100%?一直以 100% 的速度坐着? Bouncing between 50-100?在 50-100 之间弹跳? If I do go through the effort of sampling to decide what does seem to work best, is it guaranteed that switching the virtual servers' host will also work best with the same graph?如果我通过采样的努力来做 go 来决定什么似乎最有效,是否可以保证切换虚拟服务器的主机也能最好地使用相同的图表?

This added complexity I won't take into consideration for those of you willing to answer.对于那些愿意回答的人,我不会考虑这种增加的复杂性。 Feel free to ignore this section.随意忽略此部分。 However, any answer that also accounts for this complication, or even answers that just provide tips on how to handle it, I'll at the very least upvote!但是,任何也解释了这种复杂性的答案,甚至只是提供如何处理它的提示的答案,我至少会赞成!

Heck of a long question - sorry about that - and thanks for reading so much!!真是个长问题-对此感到抱歉-感谢您阅读了这么多!!

PerformanceCounter allows you to query for processor usage. PerformanceCounter允许您查询处理器使用情况。

However,have you tried something the framework provides?但是,您是否尝试过框架提供的东西?

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

You can tune the concurrency level for Tasks in the Task.您可以在任务中调整任务的并发级别。 Factory .工厂

The .NET 4 threadpool by default will schedule the number of threads it finds most performing on the hardware where it runs, but you can change how that works with the previous link.默认情况下,.NET 4 线程池将调度它发现在其运行的硬件上性能最高的线程数,但您可以使用上一个链接更改其工作方式。

Probably you need a custom solution but it would be ok to benchmark yours with the standard.可能您需要一个自定义解决方案,但可以使用标准对您的解决方案进行基准测试。

Edit: (comment note):编辑:(注释):

No links needed, I may have used an invented term since english is not my language.不需要链接,我可能使用了一个发明的术语,因为英语不是我的语言。 What I mean is: have a variable where you store the variance before the last check (prevDelta), and call it delta.我的意思是:有一个变量来存储上次检查之前的方差(prevDelta),并将其称为 delta。 add this to the varuiable avrageDelta and divide by 2, each time you 'check'.每次“检查”时,将其添加到变量 avrageDelta 并除以 2。 You will have the variable averageDelta that will mostly be low since you have no activity.您将拥有变量 averageDelta,由于您没有活动,因此该变量大多较低。 Then have another set of delta variables, one you have already (delta - prevdelta), and store it in a delta variable that is not the average of all deltas but the average of deltas in a small timespan (you will have to come up with an algortihm to calculate accurately this temporal variance).然后有另一组 delta 变量,你已经有一个(delta - prevdelta),并将其存储在一个 delta 变量中,该变量不是所有 delta 的平均值,而是一小段时间跨度内 delta 的平均值(你必须想出一个算法来准确计算这个时间方差)。 Once done this you can compare the average delta and the 'temporal delta'.完成此操作后,您可以比较平均增量和“时间增量”。 The average delta will be mostly low and will slowly go up whjen bursts come.平均增量将大部分较低,并且会在爆发时缓慢上升 go。 In the same period the temporal delta will go up really fast.在同一时期,时间增量将 go 上升非常快。 Then you have the situation when the burst stops, the average delta goes slowly down, and the 'temporal' goes really fast.然后你会遇到突发停止的情况,平均增量缓慢下降,“时间”变得非常快。

You could use I/O Completion Ports to asynchronously fetch your images without tying up any threads until it comes time to process what you have fetched.您可以使用I/O 完成端口来异步获取图像,而不会占用任何线程,直到需要处理您获取的内容。

You could then limit your thread pool based on the number of cores on your client PC, making sure to leave a core free for other processes to use.然后,您可以根据客户端 PC 上的内核数量来限制线程池,确保留出一个内核供其他进程使用。

What about a dynamic thread manager that monitors their overall performance and according to this spawns new threads or kills old ones?动态线程管理器如何监控它们的整体性能并据此产生新线程或杀死旧线程呢? The main problem here is only how to define the performance measurement function.这里的主要问题只是如何定义性能测量 function。 The rest can be done with a periodically scheduled job that increases or decreases the number of threads according to the previous number of threads and performance in that case or something like that. rest 可以通过定期调度的作业来完成,该作业根据之前的线程数和在这种情况下的性能或类似情况增加或减少线程数。 Maybe also in connection to resources utilization (CPU, disks, network...).也许还与资源利用(CPU、磁盘、网络......)有关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM