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)。

利用 PerfView 來診斷是否有 .NET Core ThreadPool Starvation 的問題

前言

因為遇到了 ThreadPool Starvation 的問題,到找了相關的文章 (Diagnostic .NET Core ThreadPool Starvation with PerfView),但閱讀英文速度太慢,避免之後又遇到此問題,又要重新看一次,就簡單的翻譯一下;希望也能幫助到有需要的人。

以下翻譯文章。

服務無法處理爆量的請求 (在 CPU 使用率 20% 的時候,可以正常作業,但是遇到爆量的請求卻沒有使用更多的 CPU 資源)

這些症狀顯示瓶頸不在 CPU。基本上是服務的請求在等待其他資源,因而無法處理爆量的請求。最常見的例子是,請求的資源來自其他的機器。

然而有一個潛在的例子,缺乏的資源就是 Thread 本身。Service 沒有 Thread 可以執行下一個請求,所以就卡在那邊等待有可用的 Thread。此時,花了較長的時間在做資料庫查詢,但是卻不是在 CPU 活動的時間發生的,看起來像是 I/O 操作導致查詢超出原本的時間。這種問題稱為 ThreadPool Starvation。