iis站點內存泄漏問題分析


 

在一次上線過程中iis內存飆升,隨后跟運維要到站點的dump文件,使用windbg分析了clr的內存分配,找到了問題的症結,先記錄如下:

使用windbg加載dump文件

1.打開windbg,File->Open Crush Dump,打開dump文件;
2.設置符號路徑和站點發布文件路徑
.sympath C:\MyCodesSymbols*SRV*C:\MyLocalSymbols* http://msdl.microsoft.com/download/symbols:C:\Users\Administrator\Desktop\symbol  
其中,C:\Users\Administrator\Desktop\symbol是pdb文件所在目錄,C:\MyCodesSymbols和C:\MyLocalSymbols均為新建文件夾存放符號文件
3.加載sos.dll和clr.dll
.load sos.dll,clr.dll文件所在的目錄(可以拷貝這兩個dll放在pdb文件目錄下)
4.加載pdb文件 .symfix
5.加載.reload
6.輸入命令.loadby sos clr
 
使用windbg命令查看堆內存
1.使用命令!dumpheap -stat 根據內存大小排序查看堆上的對象,查看占用內存比較高的對象和數組等,通過添加 -min 或者 -max 指定最小或者最大size的對象,首次執行這個命令不要添加 -min參數篩選,因為有可能就是一些小的對象比較多引起的內存問題。

 

2.使用!dumpheap -mt命令查看mt(method table)中的對象地址,上圖的第一列為mt,查看指定的MT並顯示出Address

!dumpheap -mt 000007fe9a25ebe8

第一列為對象地址(address),可以看到mt的statistic

 

3.進入這個地址查看具體的對象 !do 000000048a0eb1b0

 

 

4.查看對象引用 !gcroot 000000048a0eb1b0

 

 

5.根據上圖中的線程線程信息定位線程ID,進入線程

!threads命令查看工作的線程,71為線程ID

6.進入71線程:~71s,下圖所示已經進入71線程

7.使用!clrstack 命令查看該線程的堆棧信息

上圖可以清晰的看到大的對象經過了哪些方法的調用,再結合代碼,可以定位出問題。

 

附錄(windbg命令)

 

內存狀態:

!EEHeap -GC 顯示托管堆統計信息
!EEHeap -loader 顯示加載程序數據結構統計信息
!DumpHeap -stat 顯示垃托管堆各類型統計信息
!DumpHeap -type Free -stat 顯示所有碎片類型統計信息
!DumpHeap -type System.String -min 150 -max 200 顯示所有System.String類型 -min -max 字節統計信息
!DumpHeap -min 85000 -stat 顯示大對象統計信息
!DumpHeap -mt 選項僅列出與指定的 MethodTable 結構對應的那些對象
!DumpHeap -mt 00000000022245b0 -min 85000 查看MT 00000000022245b0中大對象
!DumpHeap -stat 023e1000 033db630 按地址統計
!DumpArray 顯示數組對象
!DumpObj (!do) 顯示有關指定地址處的對象的信息
!ObjSize 顯示指定對象的大小
!DumpStackObjects (!dso) 顯示在當前線程內找到的所有托管對象
!GCRoot 顯示有關對指定地址處的對象的引用(或根)的信息。
!CLRUsage 顯示托管堆統計信息(GC堆大小,提交內存,虛擬內存),psscor4的擴展命令
!DumpMT 顯示有關指定地址處的方法表的信息。
!DumpMT -MD 顯示有關指定地址處的方法表所有方法的列表。
!address -summary 顯示最大可用區域
!vmstat 最大可用區域是 MAXIMUM 列中的最大值

線程調用:

!ThreadPool 顯示有關托管線程池的信息,包括隊列中工作請求的數目、完成端口線程的數目和計時器的數目
!Threads 顯示進程中的所有托管線程
!Threads -live 選項顯示與活動線程關聯的線程
!Threads -pecial 選項顯示由 CLR 創建的所有特殊線程
!ThreadState 顯示線程的狀態。 value 參數為 Threads 報告輸出中的 State 字段的值。
~54s 轉到54線程
!CLRStack 提供當前托管代碼的堆棧跟蹤。
!CLRStack -p 選項顯示托管函數的參數。
!CLRStack -l 選項顯示有關幀中的局部變量的信息。
!DumpStack 顯示堆棧跟蹤 包括非托管。 
!DumpStack -EE 命令僅顯示托管函數。
!EEStack 對一個進程中的所有線程運行 DumpStack 命令。
k 顯示當前線程的call stack
kb 顯示當前線程的call stack
~*kb 顯示所有線程的call stack 可以 尋找線程中觸發GC的函數(mscorwks!SVR::GCHeap::GarbageCollectGeneration)
!ASPXPages 顯示當前處理的HttpContext,psscor4的擴展命令
!SyncBlk 顯示同步塊

其它:
!runaway 顯示線程cpu時間
vertarget 查看系統運行時間
!PrintException (!pe) 顯示在當前線程上引發的最后一個異常
!address 命令顯示某一地址上的頁信息
!SaveModule 將加載到內存中指定地址的圖像寫入指定文件,lm 列出的
!SaveModule 081f0000 d:\\commandobject.dll 
!FinalizeQueue 顯示所有已進行終結注冊的對象。
!GCHandles 顯示有關進程中的垃圾回收器句柄的統計信息。

S 可以搜索內存 在內存中搜索sina.com: s –u 0012ff40 L?8000000 “sina.com”
r 顯示寄存器的信息
d 顯示內存地址上的值 使用d命令顯示esp寄存器指向的內存,默認為byte: d esp
用dd命令直接指定054efc14地址,第二個d表示用DWORD格式: dd 054efc14

域,程序集,類
!DumpDomain 枚舉在指定的 AppDomain 對象地址內加載的每個 Assembly 對象。若在調用 DumpDomain 命令時不提供任何參數,則將列出過程中的所有 AppDomain 對象
!DumpAssembly 顯示有關程序集的信息。DumpAssembly 命令將列出多個模塊(如果存在)。
!DumpModule  顯示有關指定地址處的模塊的信息。 可以使用 DumpDomain 或 DumpAssembly 命令檢索模塊的地址
!DumpModule [-mt] 選項顯示模塊中定義的類型和模塊所引用的類型
!FindAppDomain 確定指定地址處的對象的應用程序域

!IP2MD <Code address> 顯示已 JIT 編譯的代碼中指定地址處的 MethodDesc 結構。
!DumpMD <MethodDesc address>
!U <MethodDesc address> | <Code address> 顯示由方法的 MethodDesc 結構指針或方法體內的代碼地址指定的托管方法的反匯編(帶有批注)

 

 

 


 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM