和我一起作Tess的windbg lab - Lab3, Memory
原文地址:http://blogs.msdn.com/b/tess/archive/2008/02/15/net-debugging-demos-lab-3-memory.aspx
操作步驟:
1、產生壓力:tinyget -srv:localhost -uri:/BuggyBits/Links.aspx -loop:4000
2、觀察taskmgr的輸出,w3wp的內存每秒鐘大概增長100M。
3、內存到700M左右的時候,抓一個hang dump
4、由于這是一個memory的問題,所以我們要先看GC Heap的情況,運行命令:!eeheap -gc,結果如下:
GC Heap Size? 0x2b307720(724596512)
由于dump一共870M,而GC占用了720M左右,所以我們的重點在于托管內存的分析。
5、看heap的整體狀況,運行!dumpheap -stat,結果如下:
790fd8c4??? 49787??? 721599752 System.String
嗯,720M的托管內存中,String占用了絕大多數。
6、看一下string的情況,根據2/8原則,大小相同的string也許會很多,這里我們過濾一下,看看10K以上大小的字符串,運行命令:!dumpheap -mt 790fd8c4??-min 10000
0331d6dc 790fd8c4??? 20020????
03322534 790fd8c4??? 20020????
0332738c 790fd8c4??? 20020????
0332c1e4 790fd8c4??? 20020????
0333103c 790fd8c4??? 20020?? ?
大部分都是20K的字符串,隨便找一個,我們需要看它被誰分配的
7、運行!gcroot 0331d6dc,結果如下:
Scan Thread 16 OSTHread 318
Scan Thread 18 OSTHread c38
Scan Thread 19 OSTHread a40
Scan Thread 20 OSTHread c00
Scan Thread 24 OSTHread 998
Scan Thread 14 OSTHread 4cc
Finalizer queue:Root:0331d6b8(Link)->
0331d6c8(System.Text.StringBuilder)->
0331d6dc(System.String)
在14號線程中,Link引用了這個字符串。而且我們看到,link是在Finalizer Queue中的。
8、查看finalizequeue,輸出如下:
057e0bcc??? 35998?????? 575968 Link
一共35998個Link對象。由于該對象存在于Finalizequeue中,所以一定顯示的實現了Finalize方法。
9、查看該方法,代碼如下:
~Link()
{
?????? //some long running operation when cleaning up the data
?????? Thread.Sleep(5000);
}
10、換個方向,看上面步驟7中的那個Link對象,!do 0331d6b8,輸出結果如下:
????? MT??? Field?? Offset???????????????? Type VT???? Attr??? Value Name
790fdc5c? 4000006??????? 4 ...ext.StringBuilder? 0 instance 0331d6c8 url
790fd8c4? 4000007??????? 8??????? System.String? 0 instance 029bb0b8 name
再看第一個url對象,運行!do 0331d6c8 ,結果如下:
????? MT??? Field?? Offset???????????????? Type VT???? Attr??? Value Name
791016bc? 40000b1??????? 8??????? System.IntPtr? 1 instance??? dc1d8 m_currentThread
79102290? 40000b2??????? c???????? System.Int32? 1 instance 2147483647 m_MaxCapacity
790fd8c4? 40000b3??????? 4??????? System.String? 0 instance 0331d6dc m_StringValue
注意最后一行的那個m_StringValue,對比一下步驟7中的!gcroot輸入。
從這里我們看到,Link中包含了一個StringBuilder,而StringBuilder中包含了一個20K的字符串。
11、看代碼:
public Link(string name, string url)
??? {
??????? this.name = name;
??????? this.url.Append(url);
??? }
可以看到,Link對象的構造方法中,引用了字符串。
12、再回頭看上面的步驟9,Link自作聰明的實現了Finalize方法,但是該方法執行的時間太長(這里是5秒鐘),導致垃圾回收的時候,遲遲不能把該對象回收掉。因為Link引用了字符串url,所以相應的字符串也無法被回收。這樣內存就上漲的很快了。
?
Over
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的和我一起作Tess的windbg lab - Lab3, Memory的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GContracts1.1.0支持前置/
- 下一篇: sql查table,VIEW,sp, f