0

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

4

2 回答 2

1

我从您的问题中假设您正在手动创建线程,因此回答这个问题的快速方法是建议您使用像Task Parallel Library这样的 API ,因为这将执行任意数量的任务并尝试使用合理的处理它们的线程数 - 因此给定 500 个 API 请求,它会将自身限制为仅几个线程。

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

根据您的问题编写的示例可能是这样的:

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

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

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

一个更好的例子是采用相同的场景并仅使用一个后台线程:

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

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

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

于 2013-10-31T14:57:24.520 回答
0

首先,运行分析器并检查一些重构工具,看看您是否可以执行代码优化来解决问题。如果您的应用程序仍然使服务器过载,则设置或购买负载平衡。同时,如果您正在运行最新的操作系统,您可以尝试设置一个 hacky CPU 速率限制......但是,这可能不适用于您描述的需求。

于 2013-10-31T14:54:29.047 回答