ASP NET 未使用所有可用内核 - Parallel.ForEach

ASP NET not using all available cores - Parallel.ForEach

我们的 ASP NET 软件具有应用 Parallel.ForEach 的特定条件。它运行良好,但我们最近注意到它停止为这些应用并行性的特定繁重操作使用所有可用内核。

这是我们使用的代码:

Parallel.ForEach(var1, new ParallelOptions
    { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 }, var2 => ...

我们过去在任务管理器中看到的是 32 核服务器的高使用率(如 90%),而 运行 这些特定的繁重操作。但现在它让自己只使用一个核心(仅约 5%)。过去需要 20-40 分钟,现在需要 5-6 小时!

在我们的计算机上(运行 本地 Visual Studio)我们确实看到所有内核都按预期工作(~80-90% 使用率)。

详细信息:服务器有 2x CPUs,x64,Windows Server 2012 裸机(无虚拟机)。没有硬件问题。软件在 ASP NET 4.6.2 上运行。 MaxDegreeOfParallelism 正确 returns 32. IIS Manager / Advanced Settings: CPU limit = 900. Maximum Worker Process 好像没有区别。数据库似乎不是问题,因为所有数据以前都存储在内存中(在代码中列出变量)。

由于代码过去在同一台服务器上运行良好,目前在我们的本地主机上运行良好,我们怀疑服务器端发生了某些变化。

我们怀疑 Microsoft 更新可能是导致此问题的原因,但目前我们没有发现任何问题。这些是我们怀疑的最新 2022 更新:

有人知道这个问题吗?关于如何解决此问题的任何想法?

根据设计,Parallel.ForEach 可能会使用比请求更少的线程来实现更好的性能。根据 MSDN [link]:

默认情况下,Parallel.ForEach 和 Parallel.For 方法可以使用可变数量的任务。这就是为什么,例如,ParallelOptions class 具有 MaxDegreeOfParallelism 属性 而不是“MinDegreeOfParallelism” 属性。这个想法是系统可以使用比请求更少的线程来处理循环。

.NET 线程池允许并行任务的工作线程数随时间变化,从而动态适应不断变化的工作负载。在 运行 时,系统会观察增加线程数是提高还是降低整体吞吐量,并相应地调整工作线程数。

Any ideas on how to troubleshoot this?

您可以在您的服务器上尝试 运行 这个实验,作为一个独立的控制台应用程序:

ParallelOptions options = new()
{
    MaxDegreeOfParallelism = Environment.ProcessorCount
};
int concurrency = 0;
Parallel.ForEach(Enumerable.Range(1, 100), options, item =>
{
    var current = Interlocked.Increment(ref concurrency);
    try
    {
        Console.WriteLine($"Processing {item}, Concurrency: {current}");
        for (int i = 0; i < 1_000_000_000; i++) { }
    }
    finally { Interlocked.Decrement(ref concurrency); }
});

预期的行为是看到 CPU 达到最大值 (100%),并且报告的并发数达到值 32。