2017-10-06 117 views
-1

我們的應用程序創建了許多在CLR線程池上運行的任務。 任務數量可能從10到10萬。加速CLR線程池增長

當任務數量快速增加時,許多任務在給定時間內無法完成。

這是因爲線程池每秒只添加一個新線程(儘管可能有數百個等待任務)。

下面的測試演示了此問題:

[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 上面的例子顯示的主要問題:任務是由它採用異步新的現代化圖書館創建/等待樣式代碼。但是大部分任務都是帶有線程阻塞操作的舊式遺留代碼。該應用程序工作。並且在恆定的低或恆定的高負載下它表現出良好的性能。性能問題在任務數量迅速增加時開始:儘管有數千個等待任務,但CPU利用率保持較低。

什麼是最容易的方法來應對所描述的情況?

+1

不,它被固定在半秒。它只是作爲TP線程的對策,花費很長時間才能完成它們的工作,並不意味着創建線程爆炸。設置「太長」的措施,半秒鐘。對於現代處理器來說,這是一個簡單的〜40億cpu指令,除非你計算pi的值,你只能通過過多的I/O延遲來獲得它。通用解決方案是異步代碼,這種類型不需要TP線程來等待I/O操作完成。 –

回答

0

線程池不知道任務使用async/await樣式代碼或線程阻塞代碼。 因此,它無法改變其線程管理策略。

如果您有很多舊式的傳統線程阻塞代碼,那麼只需增加線程池中的最小線程數。