IIS 慢速多线程
Posted
技术标签:
【中文标题】IIS 慢速多线程【英文标题】:IIS slow multithreading 【发布时间】:2021-10-26 14:05:02 【问题描述】:我们有一个 .NET 应用程序,它通过服务器 (IIS) 上的 OpenRia 服务进行调用。这个 Web 服务调用正在运行一个繁重的计算,我们在 LoadLibrary 上加载一些 DLL,我们需要解决一些线性系统。我们需要查看包含 1000 个事件的列表。每个事件都是一个单独的计算,并且可以彼此独立运行。 我们正在做的是,我们在 64 核机器上创建 60 个任务,每个任务都接受一个事件 => 运行计算 => 接受下一个事件 => 运行计算,依此类推,直到列表为空。 一旦列表为空,我们的计算就完成了。
我们现在有一个奇怪的行为,即在第一次运行时计算似乎运行得很快,但是当我们再次运行相同的计算时,每次运行都会变慢。 如果我们重新启动服务器,计算会再次快速运行。
我们使用 PerfView 进行了分析,我们发现在第二次/第三次/第四次运行时,来自 IIS 工作进程的已用线程比开始时要少。 在第一次运行时,IIS 工作进程使用了 60 个线程(正如我们所定义的那样),而在第二次运行时,该进程使用的线程数少于 60。每次运行时,实际使用的线程越来越少。 第一次运行计算需要大约 3 分钟。第二次运行我们需要 6 分钟,第三次运行我们已经在 15 分钟左右。
可能是什么问题?我曾尝试使用 ThreadPool,但效果与使用 Tasks 相同。
这里是一些示例代码:
//This part of code is called after the web service call
ConcurrentStack<int> events = new ConcurrentStack<int>();//This is a list of 1000 entries
ParallelOptions options = new ParallelOptions();
int interfacesDone = 0;
Task[] tasks = new Task[options.MaxDegreeOfParallelism];
for (int i = 0; i < options.MaxDegreeOfParallelism; i++)
tasks[i] = Task.Run(() =>
StartAnalysis(events);
);
Task.WaitAll(tasks);
private void StartAnalysis(ConcurrentStack<int> events)
while (!events.IsEmpty)
int index;
if (events.TryPop(out index))
DoHeavyCalculation();
【问题讨论】:
你能贴一些代码吗? IIS 本身利用线程池来处理传入请求,因此它会分配专用线程并确保它们在需要时可用。因此,如果您的 Web 应用程序还想要执行繁重的操作并使用线程(无论您使用哪个 .NET 多线程 API),那么您就会引入冲突和争用。要解决此类争用,可行的选择是重新设计您的 Web 应用程序并将繁重的操作移至其他进程。无论如何,这不是一个简单/简单的答案。 我不确定的是:我们只向服务器发出一个请求。在计算完成之前没有其他请求。为什么第一次这么快,第二次这么慢?我们肯定会尝试在 IIS 进程之外进行计算。 "但是当我们再次运行相同的计算时,每次运行都会变慢。如果我们重新启动服务器,计算再次运行得很快。" - 听起来你没有正确处理资源。 如果没有处理某些东西,内存应该会增加很多。但是经过 3,4 次运行后,我们的大小大致相同。工作完成后,线程不应该被销毁吗? 【参考方案1】:ASP.NET 使用 .NET 线程池中的线程处理请求。线程池维护了一个已经产生线程初始化成本的线程池。
因此,这些线程很容易重用。 .NET 线程池也是自我调整的。它监控 CPU 和其他资源利用率,并根据需要添加新线程或修剪线程池大小。
【讨论】:
有办法监控吗? 您可以使用性能计数器来监控线程。这个article 展示了许多监控应用程序和 IIS 的方法。你可以参考一下。以上是关于IIS 慢速多线程的主要内容,如果未能解决你的问题,请参考以下文章