上篇文章給大家解釋了Windbg的基本命令和說明,這一篇給大家介紹內(nèi)存泄露場(chǎng)景的問題分析。
文章大綱:
* 描述問題背景和現(xiàn)象
* 確定問題是否是內(nèi)存泄露
* 梳理問題分析思路
* 動(dòng)手分析解決
* 總結(jié)
1. 先說問題背景:生產(chǎn)環(huán)境IIS站點(diǎn),運(yùn)行一段時(shí)間后,w3wp進(jìn)程內(nèi)存會(huì)漲到2G,同時(shí)內(nèi)存不釋放。
2. 問題確認(rèn)
打開性能計(jì)數(shù)器,我們重點(diǎn)看一段時(shí)間內(nèi),IIS站點(diǎn)w3wp進(jìn)程相關(guān)的性能計(jì)數(shù)器的變化:
性能計(jì)數(shù)器中:有三個(gè)非常重要:
.NET CLR Memory/Gen 2 heap size
.NET CLR Memory/Gen 1 heap size
.NET CLR Memory/Gen 0 heap size
托管堆上的對(duì)象有三代:
第 0 代: 這是最年輕的代,其中包含短生存期對(duì)象。 短生存期對(duì)象的一個(gè)示例是臨時(shí)變量。
垃圾回收最常發(fā)生在此代中。新分配的對(duì)象構(gòu)成新一代的對(duì)象并且為隱式的第 0 代回收,除非它們是大對(duì)象,在這種情況下,它們將進(jìn)入第 2
代回收中的大對(duì)象堆。大多數(shù)對(duì)象通過第 0 代中的垃圾回收進(jìn)行回收,不會(huì)保留到下一代。
第 1 代: 這一代包含短生存期對(duì)象并用作短生存期對(duì)象和長(zhǎng)生存期對(duì)象之間的緩沖區(qū)。
第 2 代: 這一代包含長(zhǎng)生存期對(duì)象。 長(zhǎng)生存期對(duì)象的一個(gè)示例是服務(wù)器應(yīng)用程序中的一個(gè)包含在進(jìn)程期間處于活動(dòng)狀態(tài)的靜態(tài)數(shù)據(jù)的對(duì)象。
當(dāng)條件得到滿足時(shí),垃圾回收將在特定代上發(fā)生。 回收某個(gè)代意味著回收此代中的對(duì)象及其所有更年輕的代。 第 2
代垃圾回收也稱為完整垃圾回收FullGC,因?yàn)樗厥账写系乃袑?duì)象(即,托管堆中的所有對(duì)象)。
幸存和提升:垃圾回收中未回收的對(duì)象也稱為幸存者,并會(huì)被提升到下一代。 在第 0 代垃圾回收中幸存的對(duì)象將被提升到第 1 代;在第 1
代垃圾回收中幸存的對(duì)象將被提升到第 2 代;而在第 2 代垃圾回收中幸存的對(duì)象將仍為第 2 代。
通過代提升,看對(duì)象的存活時(shí)間!
Process/Private Bytes
Process/Virtual Bytes
.NET CLR Memory/# Bytes in all Heaps : CLR內(nèi)存托管堆的大小
.NET CLR Memory/Large Object Heap Size: 大對(duì)象堆包含其大小為 85,000 個(gè)字節(jié)和更多字節(jié)的對(duì)象。
托管堆的內(nèi)存大小增加的趨勢(shì)和大對(duì)象堆增加的趨勢(shì)重疊,可以初步推斷,內(nèi)存的增加和大對(duì)象有關(guān)系!
3. 梳理問題分析思路
連續(xù)、間隔抓兩個(gè)或者三個(gè)Dump,每次抓Dump間隔半個(gè)小時(shí),或者一個(gè)小時(shí),主要看內(nèi)存的增量。
對(duì)比的看每個(gè)Dump中:
* 多核CPU情況下,分析每個(gè)GC托管堆的大小 !eeheap –gc
* 查詢內(nèi)存中各類對(duì)象的總個(gè)數(shù)和總內(nèi)存占用 !dumpheap –stat
* 查詢內(nèi)存中大對(duì)象的個(gè)數(shù)和對(duì)象大小 !dumpheap –stat -mt -min 5000 -max 100000
* 如果某一類或者幾類對(duì)象的內(nèi)存總占用很多,分析此類對(duì)象 !dumpheap –mt ***
* 多次采樣查看步驟4中對(duì)象的gcroot !gcroot addr
* 打斷gcroot中任何一個(gè)鏈條,釋放對(duì)象引用
4. 動(dòng)手分析
* 多核CPU情況下,分析每個(gè)GC托管堆的大小 !eeheap –gc
? ? ??
* 查詢內(nèi)存中各類對(duì)象的總個(gè)數(shù)和總內(nèi)存占用 !dumpheap –stat
? ? ??
* 查詢內(nèi)存中大對(duì)象的個(gè)數(shù)和對(duì)象大小 !dumpheap –stat -mt -min 5000 -max 100000
? ? ??
??
* 如果某一類或者幾類對(duì)象的內(nèi)存總占用很多,分析此類對(duì)象 !dumpheap –mt *** -stat
? ? ??
? ? ? 大對(duì)象字符串分析,Session會(huì)話數(shù)據(jù)!同時(shí)Session會(huì)話中包含了權(quán)限數(shù)據(jù)!
* 多次采樣查看步驟4中對(duì)象的gcroot !gcroot addr
? ? ??
* 打斷gcroot中任何一個(gè)鏈條,釋放對(duì)象引用
5. 總結(jié)
總結(jié)一下,內(nèi)存泄露問題分析,有固定的方法和指令,過程需要大家深入理解,同時(shí)熟悉代碼非常重要,因?yàn)樾枰页鰃croot,分析出內(nèi)存泄露的原因,再進(jìn)行修改解決。
大的套路:
* 描述問題背景和現(xiàn)象
* 確定問題是否是內(nèi)存泄露
* 梳理問題分析思路
* 動(dòng)手分析解決
* 總結(jié)
詳細(xì)的分析步驟:
* 多核CPU情況下,分析每個(gè)GC托管堆的大小 !eeheap –gc
* 查詢內(nèi)存中各類對(duì)象的總個(gè)數(shù)和總內(nèi)存占用 !dumpheap –stat
* 查詢內(nèi)存中大對(duì)象的個(gè)數(shù)和對(duì)象大小 !dumpheap –stat -mt -min 5000 -max 100000
* 如果某一類或者幾類對(duì)象的內(nèi)存總占用很多,分析此類對(duì)象 !dumpheap –mt ***
* 多次采樣查看步驟4中對(duì)象的gcroot !gcroot addr
* 打斷gcroot中任何一個(gè)鏈條,釋放對(duì)象引用
歡迎大家補(bǔ)充。
?
周國(guó)慶
2018/10/30
熱門工具 換一換