透過 WinDbg 來找出 ASP.NET CPU 100% ASP.NET 程式的問題

問題

我們有一個 ASP.NET 的系統部署到 IIS 上(Windows 2012, .NET 4.x),有時候會導致 w3wp.exe 吃掉所有的 CPU 資源,一直要等到應用程式回收後,程式再重新啟動後就正常了。這種狀況不定期會發生。

解法

我們可以使用 WinDbg 來找出導致 IIS CPU 100% 的原因,方法如下,

  • 透過「工作管理員」來「建立傾印檔案」
    當發生 IIS 導致 CPU 100% 時,開啟「工作管理員」,按右鍵選取「建立傾印檔案」。要依 Web 應用程式的平台(x86/x64)來開啟「工作管理員」(x86的工作管理員在 C:\Windows\SysWOW64\taskmgr.exe )。
  • 安裝 WinDbg
    請參考 Debugging Tools for Windows (WinDbg, KD, CDB, NTSD) 來安裝對應的版本。
  • 設定 Symbol Path
    先建立一個 C:\RTX64_SYMBOLS 目錄(依您自行定義),然後開啟 Command 設定 _NT_SYMBOL_PATH 的環境變數,如下,

    set _NT_SYMBOL_PATH=srv*C:\RTX64_SYMBOLS*https://msdl.microsoft.com/download/symbols

    set _NT_SYMBOL_PATH所以在 command 中,輸入 set 後,就可以看到 _NT_SYMBOL_PATH 的設定值哦,

    _NT_SYMBOL_PATH當然,如果常常會用到的話,就直接設定到 環境變數之前,下次 debug 時,就不用再設定一次了哦! 詳細請參考Set up your system to use Microsoft’s public Symbol Server

  • 在 WinDbg 中找問題
    • 載入 sos.dll
      WinDbg 有 x86/x64 的版本,我是使用 x64 的版本,所以 sos.dll 的路徑是 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll,您輸入如果發生錯誤的話,請使用 C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll 。
    • 設定 Symbol 檔目錄
      !sym noisy
      .cordll -ve -u -l
    • 透過 !runaway 顯示Threads所佔的時間
      輸入 !runaway 後,會顯示各 Thread 所花費的時間,花最多的會在最上面,如下圖,

      !runaway

      !runaway

    • 透過 ~[thread]s 切換到該 thread 的位置
      由上圖所示,Thread 40 佔最多時間,所以我們切到它的位罝去,

      ~40s

      ~40s

    • 透過 !clrstack 來查看呼叫堆疉
      !clrstack

      !clrstack從上圖可以發現,應該是有關 Dictionary 操作的問題,而它是由我們系統中 TemplateCfg.initial() 這個 Method 所引起的。

  • 檢視並調整程式碼
    開啟 TemplateCfg 程式碼,在 initial 這個 Method 之中會建立 Dictionary 物件,Clear 它,並 Insert 資料,但這些 Dictionary 的變數卻又設定成 static 。TemplateCfg.initial()即然這些 Dictionary 是 static 的,而且它們值又都是相同的,就沒有必要每次 request 時,就重新建立並 insert 這些資料。
    所以將 initial 裡面的 Code 搬到 static constructor 。
    調整完程式碼後,從去年觀察到目前,已經沒有再發生 CPU 100% 的狀況。

參考資料

Debugging in Production Part 1 – Analyzing 100% CPU Usage Using Windbg
WinDBG 應用實例:找出 ASP.NET CPU 100% 原因
Debugging Tools for Windows (WinDbg, KD, CDB, NTSD)
Set up your system to use Microsoft’s public Symbol Server
High CPU Hangs – 05
中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件
Intro to WinDBG for .NET Developers
.NET Debugging Demos Lab 4: High CPU Hang – Review

如何在.Net專案中開始使用TypeScript

在介紹如何在.Net專案中開始使用TypeScript之前先來講講,在使用JavaScript時曾經碰過的幾個問題:

1. JavaScript沒有OO
若要讓JavaScript有OO的特性就必須透過Protype來達成,但問題是需要多輸入一些程式碼,寫法如下圖所示:

2.誤用ES6或是ES7的語法
在開發JavaScript有時不會特別留意是使用哪一個版本新增的語法,如果不小心用到比較新的語法時,會讓舊版本的瀏覽器 (如:IE) 無法運行。

<下圖> Foo2 為ES6新增的寫法,程式碼雖然精簡,但是在IE上是無法運行,因為IE不支援ES6以上的語法。

3.只有在偵錯時才知道有沒有語法錯誤
是用JavaScript開發時,往往都要在瀏覽器執行時才會知道這段JS有沒有語法錯誤。
在用TypeScript開發時,在編譯的階段就可以知道語法有沒有錯誤,可以大幅減少除錯的時間。

<下圖>   IDE在編譯之前就已經抓到錯誤的語法:


接下來介紹要如何在.Net專案設定TypeScript
Step 1.開發環境

(1) TypeScript
TypeScript安裝途徑有兩個:
● 安裝Visual Studio時順便安裝。
● Visual Studio擴充功能 → 搜尋TypeScript → 下載並安裝。

(2) Visual Studio版本:Visual Studio 2017、Visual Studio 2015、Visual Studio 2013 (不確定是否可以)

Step 2.新增tsconfig.json (TypeScript設定檔)

專案根目錄 → 新增新項目 → TypeScript設定檔

Step 3.編輯tsconfig.json

如果要將所有的TS檔編譯成1個JS檔,可以將下圖”outDir”換成”outFile”,後面的目錄加上JS的檔名。
tsconfig的屬性有很多就不全部介紹了,有興趣的話可以到官網看看

Step 4.加入TS檔,並開始開發

TS檔編輯完後存檔後會在專案目錄下可以看到JS檔和Map檔,這樣就大功告成了。
注意:當TS檔有錯誤時,不會編譯JS檔和Map檔


在開發Typescript時難免會引用外部的JavaScript套件,但是在外部的JavaScript套件會遇到一個問題,那就是在使用外部JS的物件時,會出現錯誤訊息,如下圖所示:
這個問題的解法上在TS加入紅色圈起的程式碼後,錯誤訊息就消失了,問題也就排除了。

最後,提供一下TypeScript學習的資源,希望各位能夠順利開發。

TypeScript官方文件 (英文)
HackMD – TypeScript新手入門 (正體中文)
GitBook – TypeScript 入門教學 (簡體中文)