线程进入CPU性能

时间:2013-10-31 14:40:49

标签: c# multithreading parallel-processing

我有一个控制台应用程序(c#),我必须调用各种第三方API并收集数据。我必须同时为不同的用户做。我正在使用线程。但随着用户数量的增加,这项服务正在进入CPU性能。它正在影响其他进程。有没有办法可以使用线程进行并行处理,但不会以很大的方式影响CPU性能。

2 个答案:

答案 0 :(得分:1)

我从您的问题中假设您手动创建线程,因此快速回答此问题的方法是建议您使用Task Parallel Library之类的API,因为这将需要任意数量的任务和尝试使用合理数量的线程来处理它们 - 因此,如果给出500个API请求,它将仅限于几个线程。

但是,要更详细地回答:您会看到此问题的典型原因是代码创建了太多线程。线程不是免费资源 - 它们很昂贵。

基于您的问题的组成示例可能是这样的:

  • 您需要调用5个第三方API,每个API将返回每个用户大约1MB的数据
  • 您在每个用户的单独后台线程上调用每个API
  • 您有100个用户
  • 因此,您总共创建了500个线程,每个线程都在等待来自网络的数据

这里的问题是该程序试图管理500个线程,并且它们都在等待系统中最慢的部分 - 网络。

更简单地说,我们试图一次下载500个数据(在这个例子中意味着一切都要慢慢完成),而不是一次下载一个,这样单个项目就可以提前完成。因为每个线程都不做任何事情(只是等待网络),CPU将不断地在空闲线程之间切换。当您增加用户数时,线程数会增加 - 这会增加CPU使用率,仅用于线程之间的切换,即使每个线程实际上下载速度较慢。这(大约)为什么当用户数量增加时你会看到性能下降的原因。

更好的示例将采用相同的方案并仅使用一个后台线程:

  • 您需要调用5个第三方API,每个API将返回每个用户大约1MB的数据
  • 每个API调用都放入队列,队列由单个线程处理
  • 您有100个用户
  • 因此,您在后台运行了一个线程,该线程正在为每个请求使用网络的完整可用带宽

在此示例中,您的CPU使用率将非常一致 - 无论您拥有多少用户,只有一个后台线程在运行,因此上下文切换最小化。每个API调用都以网卡的最大速率运行,因此尽快完成。

现实情况是,一个线程可能还不够:单个请求不太可能使网络饱和,因为其他地方会有限制因素。但是这是你可以稍后调整的东西:也许2或3个线程会更高效,但4个线程会再次变慢。线程化时的一般规则是从小开始并处理,而不是为每个工作创建一个线程。

答案 1 :(得分:0)

首先,运行profiler并检查一些refactoring工具,看看是否可以执行代码优化来解决问题。如果您的应用程序仍在使服务器超载,请设置或购买load balancing。与此同时,如果您正在运行最新的操作系统,您可以尝试设置一个hacky CPU rate limit ...但是,这可能不适合您描述的需求。