用windbg+sos找出程序中誰佔用內存太高,誰佔用CPU太高(轉載)

原文地址:html

http://www.cnblogs.com/Lawson/archive/2011/01/23/1942692.htmlweb

 

很早看到windbg+sos方面的知識,一直沒仔細學習,也許由於本身作的系統還不夠複雜,也沒線上真實環境查看的權限,一直沒學習這方面的知識,最近幾天仔細找了這方面的資料,本身也寫了個可能形成高CPU高內存的測試web頁面,發現確實不錯,即便一個生手,也能夠用工具連蒙帶騙的猜出哪裏出了問題,固然對一些命令和內部標示更熟悉了後,能夠更好的找出問題所在,很是值得學習。我在使用過程當中,也遇到大量問題,好比系統兼容,軟件版本,.net版本等,部分我也沒能理解清楚,但如今確實用它找到了程序的問題,所以做個記錄,爲之後本身或你們查閱資料提供必定的方便。windows

基本工做:框架

我用的windbg是6.11.1.404的32位版本,微軟官網下載地址:http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx#b,SOS是每一個.net框架都自帶的,我用的.net4.0的sos.dll,個人在C:\Windows\Microsoft.NET\Framework\v4.0.30319裏面,另外我還用了調式的pdb符號文件,若是不下載,能夠配置須要的時候自動下載,但下載須要選擇操做系統版本。windbg老版本使用過程當中報過mscorlib的什麼錯誤,具體記不起了,但之前別人用起過,我確實用不起,換新版本就行了。dom

配置工做及經常使用命令:工具

在windbg主窗口點擊File下面的Symbol Search Path,設置符號文件路徑,好比個人:C:\Windows\symbols\dll;srv*C:\symbols*http://msdl.microsoft.com/download/symbols,其實C:\symbols纔是我下載的符號文件安裝位置,http://msdl.microsoft.com/download/symbols這個是必須的,由於找不到符號文件,它會自動從這裏下載。也能夠從註冊表設置,但我沒在註冊表設置它。學習

我在調試過程當中windbg界面以下:測試

通常咱們找到程序出問題大致的地方,能夠直接查看對應代碼,若是沒源代碼,咱們一樣能夠用windbg導出指定程序集地址的代碼,而後反編譯看到源代碼,尤爲好比部分dll文件是其餘團隊的代碼,咱們看不到的時候。spa

經常使用命令好比:操作系統

第一步通常是.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll,加載sos,這樣才能調試託管代碼

查看引發CPU太高命令好比:

!threadpool,查看線程池CPU使用量,我認爲WEB的好比iis應用程序池進程w3wp若是CPU使用太高,那查看線程池命令確定看的出來太高,這個是我本身的理解,c/s的就不必定了。

!runaway,查看線程佔用CPU時間,能夠從中找到哪一個線程佔用時間更高。

~number s,number爲具體哪一個線程的ID。

!clrstack,到具體某個線程後,查看當前線程的託管代碼

!name2ee ,找到哪一個託管代碼模塊後,查看MethodTable,EEClass等信息。

!dumpmt,找到相關MethodTable處的相關信息。

!dumpmd,根據MethodDesc找到相關模塊信息,好比MethodTable.

!dumpdomain,顯示全部域裏的程序集,或者根據參數獲取指定域。

!savemodule,根據具體程序集地址,把當前程序集的代碼生成到指定文件

查看佔用內存太高的命令好比:

!eeheap,查看堆中信息,能夠查看到大對象。

!dumpheap,查看堆中信息,通常帶-min,-stat,-type等參數。

!gcroot,根據堆地址,查看相關模塊引用代碼信息。

其餘命令固然還很是多,也很是有用,須要的時候再翻資料,若是須要很精通windbg+sos,仍是老老實實仔細看吧。

 

開始調試:

通常分析dump文件方式,能夠直接附加進程分析,也能夠保存dump文件,再單獨線下分析。  在線調試,直接Attach to a process就能夠了,通常線下調試,能夠用windbg的

adplus.vbs生成dump文件,命令以下:adplus -hang -o d:\dump -p 1234,其中hang表示附加到進程,若是是—crash,則爲目標進程崩潰的時候抓取,-o後面的參數表示dump文件放到說明位置,-p後面的數字爲進程的PID,也能夠是-pn後面跟進程名稱。在個人使用過程當中,win7的系統,用adplus抓取w3wp進程老失敗,抓其餘普通進程沒問題,最終我用windows任務管理器查看到的進程界面,點擊w3wp進程,右鍵建立轉儲文件,它自動生成的dmp的dump文件到臨時目錄,這裏它建立的dump文件大小將遠遠大於當前進程的實際大小。

 

個人測試程序在VS2010下的MVC2代碼以下:模擬常見的程序形成循環過大,靜態事件綁定到實例對象,形成不釋放內存等會引發CPU過大,內存太高的問題。

複製代碼
 1     public class HomeController : Controller
 2     {
 3         public static event EventHandler MyEvent;
 4         List<byte[]> list = new List<byte[]>();
 5         public ActionResult Index()
 6         {
 7             ViewData["Message"] = "歡迎使用 ASP.NET MVC!";
 8 
 9             MyEvent += new EventHandler(TestEvent);
10             MyEvent(null, new EventArgs());
11             MyMethod();
12 
13             return View();
14         }
15 
16         public void MyMethod()
17         {
18             long i = 0;
19             while (i < 999000000)
20             {
21                 i++;
22             }
23         }
24 
25         public void TestEvent(object obj, EventArgs args)
26         {
27             for (int i = 0; i < 20; i++)
28             {
29                 list.Add(new byte[1024 * 1024 * 10]);
30             }
31         }
32     }
複製代碼

 

 

訪問/home/index後,形成我CPU立刻升到50%左右,內存倒看不出來,但多個訪問後會有沒法釋放的內存愈來愈大。

首先載入sos後,下面是個人命令記錄:(.........爲省略更多內容,因爲我記錄的時候線程已經切換到25了,顯示0:025>了)

0:025> !threadpool
CPU utilization: 51%

...................

查看什麼線程佔用CPU多一點

0:025> !runaway
 User Mode Time
  Thread       Time
  25:920       0 days 0:00:03.042
   0:150c      0 days 0:00:00.046
   9:6c        0 days 0:00:00.015
  27:1598      0 days 0:00:00.000
  26:15cc      0 days 0:00:00.000
  24:1084      0 days 0:00:00.000

切換到25線程:

0:025> ~25s
eax=2362d4fc ebx=00000000 ecx=00000001 edx=00000000 esi=01c9e838 edi=01ca4934
eip=00d70746 esp=0e2dee44 ebp=0e2dee58 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
00d70746 8bd9            mov     ebx,ecx

查看託管代碼:

0:025> !clrstack
OS Thread Id: 0x920 (25)
Child SP IP       Call Site
0e2dee44 00d70746 DumpWebTests.Controllers.HomeController.MyMethod()
0e2dee60 00d70580 DumpWebTests.Controllers.HomeController.Index()

...............................

0:025> !name2ee * DumpWebTests.Controllers.HomeController
Module:      64bd1000
Assembly:    SMDiagnostics.dll

................

Module:      008b689c
Assembly:    DumpWebTests.dll
Token:       02000004
MethodTable: 0130002c
EEClass:     00c84348
Name:        DumpWebTests.Controllers.HomeController

查看模塊信息:

0:025> !dumpmt 0130002c
EEClass:      00c84348
Module:       008b689c
Name:         DumpWebTests.Controllers.HomeController
mdToken:      02000004
File:         C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\9f8ccc72\b9d96a8\assembly\dl3\9b2cfeec\916cd56e_eebacb01\DumpWebTests.dll
BaseSize:        0x38
ComponentSize:   0x0
Slots in VTable: 45
Number of IFaces in IFaceMap: 6

查看全部程序集:

0:025> !dumpdomain

查看到下面的信息:

  Module Name
008b689c            C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\9f8ccc72\b9d96a8\assembly\dl3\9b2cfeec\916cd56e_eebacb01\DumpWebTests.dll

Assembly:           00e4b2c8 [C:\Windows\assembly\GAC_MSIL\System.Web.Mvc\2.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll]
ClassLoader:        00e234f8
SecurityDescriptor: 00e82280

保存程序集:

0:025> !savemodule 008b689c d:\dump\out.dll
3 sections in file
section 0 - VA=2000, VASize=39c4, FileAddr=200, FileSize=3a00
section 1 - VA=6000, VASize=320, FileAddr=3c00, FileSize=400
section 2 - VA=8000, VASize=c, FileAddr=4000, FileSize=200

已經把分析出的有問題的程序dll保存到d盤dump目錄的Out.dll文件了,若是有源代碼,固然能夠直接查看對應方法的代碼,這個就把CPU太高的程序找到了,具體緣由固然還要本身分析代碼了,

分析內存太高的方法,前面的經常使用方法裏按照步驟就能找到了,這裏就不寫到博文裏了。

 

其實我也還對windbg+sos調試代碼的方式比較陌生,還不夠熟悉,可是仍是像最開始說的,只要稍微比較熟悉了,連蒙帶差仍是能大致找處處問題的地方,精確找到問題,仍是須要進一步的學習。

本篇文章中,也許有不對的地方,若是發現,請指正,防止本身和你們之後出現一樣的問題:)

相關文章
相關標籤/搜索