加速CLR中的线程池增长

时间:2017-10-06 11:06:58

标签: .net task clr threadpool

我们的应用程序创建许多在CLR线程池上运行的任务。 任务数量可能从10到10万。

当任务数量快速增加时,许多任务无法在给定时间内完成。

这是因为线程池每秒只添加一个新线程(尽管可能有数百个等待任务)。

以下测试说明了问题:

[Test]
public void TestTasks()
{
    ThreadPool.SetMaxThreads(10000, 10000);
    ThreadPool.SetMinThreads(1, 1);
    var source = new CancellationTokenSource();
    for (int i=0; i<1000; i++)
    {
        int ci = i;
        Task.Run(() => {
            Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + $" {ci} - START");
            Thread.Sleep(TimeSpan.FromSeconds(5)); // long operation simulatation
            Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + $" {ci} - FINISH");
        }, source.Token);
    }
    Thread.Sleep(TimeSpan.FromSeconds(10));
    source.Cancel();
}

典型输出

01:38:37.171 0 - START
01:38:37.171 1 - START
01:38:37.172 2 - START
01:38:37.172 3 - START
01:38:38.029 4 - START
01:38:39.029 5 - START
01:38:40.030 6 - START
01:38:41.031 7 - START
01:38:42.029 8 - START
01:38:42.172 0 - FINISH
01:38:42.172 9 - START
01:38:42.173 3 - FINISH
01:38:42.173 1 - FINISH
01:38:42.173 2 - FINISH
01:38:42.173 10 - START
01:38:42.173 11 - START
01:38:42.173 12 - START
01:38:43.029 13 - START
01:38:43.030 4 - FINISH
01:38:43.030 14 - START
01:38:44.030 5 - FINISH
01:38:44.030 15 - START
01:38:44.030 16 - START
01:38:45.029 17 - START
01:38:45.031 6 - FINISH

有没有办法提高线程池增长的速度?

更新1。 上面的例子显示了主要问题:任务是由使用async / await样式代码的新现代库创建的。但是大多数任务都是具有线程阻塞操作的旧遗留代码。该应用程序工作。在恒定的低或恒定高负载下,它表现出良好的性能。当任务数量快速增加时,性能问题就开始了:虽然有数千个等待任务,但CPU利用率仍然很低。

应对上述情况的最简单方法是什么?

1 个答案:

答案 0 :(得分:0)

线程池不知道任务使用async / await样式代码或线程阻塞代码。 因此,它无法改变其线程管理策略。

如果你有很多旧式的遗留线程阻塞代码,那么只需增加线程池中的最小线程数。