2019年8月9日 星期五

[心得] .NET ThreadPool Starvation

最近遇到了應用程式在執行的時候,CPU 的使用率不高,但是程式像是不會動了一樣 (不是 Hang 住那樣),送過去的 Request 都沒有回應,過了幾秒鐘之後,才有回應。後來發現跟 ThreadPool Starvation 有關。

之前被教導盡量使用 ThreadPool,因為它會幫我們管理 Thread,但是卻沒有注意到使用上的一些細節。

因為 Thread 的使用相當耗費資源,而 ThreadPool 會幫我們管理 Thread 的生成,讓我們可以重複的使用 Thread,使我們的程式更有效率。但為了讓重用 Thread,ThreadPool 預設以 Processor 的數量來決定 ThreadPool 中最少的 Thread 數,例如: 我的電腦 (下圖) 有 2 Cores, 4 Logical Processors,ThreadPool 最少有四條 Thread (worker thread: 4, completion port thread: 4)。





因為 ThreadPool 中 Thread 一開始的數量只有四條 (以我的例子來說),所以當同一時間很多工作被放到 ThreadPool 的佇列中,而這些工作沒辦法在短時間消化完的情況下,ThreadPool 會開始建立新的 Thread 來執行這些工作,但是建立 Thread 的速度很慢,大約每秒建立一到兩個 Thread。

這也就是為什麼程式會看起來像是不動了一樣,因為這些工作透過 ThreadPool 去執行,但是 Thread 已經用完了,卻沒有 Thread 來做這些新的工作,必須等待 ThreadPool 建立新 Thread。所以過幾秒後,才又有可用的 Thread 來完成新的工作,這時程式才又有回應。

所以排入 ThreadPool 中的工作,執行的時間最好不要太長,否則後面排入的工作可能就要等很久才會執行到,這樣就餓死拉 (ThreadPool Starvation)。

主要參考的文章: https://blogs.msdn.microsoft.com/vancem/2018/10/16/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall/

沒有留言: