[xperf] 查 memory leak 初步

[xperf] 查 memory leak 初步

這幾天在查程式的 memory leak,查的真是昏天暗地…

要嘛覺得是這邊,修改一下,沒什麼效果,

要嘛覺得有可能是這邊,可是邏輯上又看不出有什麼問題 Orz…

後來還是決定用 xperf 來看看能不能幫上忙…

最後是有幫上忙,但是在使用 xperf 時也遇到了不少問題,

一邊還要解決這些 xperf 的問題,真的是焦頭爛額…

不過幸好,最後「似乎是」有把 memory leak 找到原因了~

(說「似乎是」是因為…暫時的看不出來記憶體的持續增長狀況,

但你永遠不知道是不是還有潛藏的問題…

基本上,就先這樣吧~~ :P)

 

重點1:xperf 最好是使用在 Windows 7 以上

雖然微軟說你也可以把 xperf 的檔案複製到 Windows XP 上跑(參考這裡),

但最後分析還是要放在 Windows 7 的電腦上,

而且在 Windows 7 上資料收集可以比較集全,

因此,最好還是選擇在 Windows 7 上使用囉~~

反正現在虛擬機器很流行,這應該不是大問題~

 

重點2:xperf 不能與 SysInternal Process Explorer 一起跑

Process Explorer 是寫 Windows 程式的人很喜歡用的工具,

我也幾乎總是一直開著它,就算在家裡的電腦也會開來看看現在什麼 process 在跑 😛

但是!由於未知的原因(其實是我懶得查),

Process Explorer 在執行的時候,是無法用 xperf 來記錄事件的!

因此,想用 xperf 的時候,請乖乖的用回工作管理員吧~

 

接下來就看看要怎麼用 xperf 來查 memory leak 吧~

 

步驟1:首先開啟一些基本的 logging:

xperf -on Base -BufferSize 2048  -MinBuffers 10 -MaxBuffers 16 -f kernel.etl

 

步驟2:接下來,用下列的指令來讓 xperf 開始監視 pid 是 xxx 的 process

xperf -start HeapSession -heap -Pids xxx -BufferSize 2048 -MinBuffers 128 -MaxBuffers 128 -stackwalk HeapAlloc+HeapRealloc -f heap.etl

 

步驟3:開始做一些會讓受測的 process 產生 memory leak 的動作,

像我這次測的程式在平常放著不管它,或是複製檔案時都會有 leak(太慘了 =_=),

因此我就會測試這兩種情境~

 

步驟4:用下列的指令停止 xperf logging 並將 kernel.etl 和 heap.etl 合併:

xperf -stop -stop HeapSession
xperf -merge kernel.etl heap.etl merge.etl

這邊要注意的是,合併完的檔案大小不一定會等於 kernel.etl 和 heap.etl 的相加大小,

不過應該至少要比它們兩個都大!

 

步驟5:產生 memory leak 分析報告,下面的指令是列出前 25 名最嚴重的部分:

xperf -i merge.etl -o stacks.txt -symbols verbose dbghelplog -a heap -stacks so -top 25

你可以把 -top 的值設比較大,不過相對應的處理時間也會變長…

 

處理完後的 stacks.txt 就會包含 memory leak 產生的地方的 stack,下面是一個例子:

Results for process yyy.exe (4716):
---------------------------------------------------------------------
GLOBAL ALLOCATIONS:
Alloc       :    17727522,    4925268.6 KB
Realloc     :         169
Outstanding :       12828,       1529.1 KB
---------------------------------------------------------------------
TOP 25:
Alloc       :       13988,       1644.1 KB
Realloc     :           0
Outstanding :       10117,       1271.2 KB
---------------------------------------------------------------------
ntdll.dll! ?? ::FNODOBFM::`string'
xxx.dll!calloc
xxx.dll!_wcsdup
xxx.dll!Function8
xxx.dll!Function7
xxx.dll!Function6
xxx.dll!Function5
xxx.dll!Function4
xxx.dll!Function3
xxx.dll!Function2
xxx.dll!Function1
kernel32.dll!BaseThreadInitThunk
ntdll.dll!RtlUserThreadStart
Alloc       :        2264,        327.9 KB
Realloc     :           0
Outstanding :        2264,        327.9 KB

 

從上面的例子就可以看到,xxx.dll 裡面有個 memory leak,

接著只要再去相關的程式碼裡面看看就可以了~~

其實雖然這裡已經列出來函式名稱,不過並沒有參數內容,

因此有時候其實還是不容易看出來問題在哪裡,

必須仔細的 trace code 才行…

 

重點3:如果在 stacks.txt 裡面發現有 xxx.dll!? 這種字串的話,表示 symbol 不正確。

請將正確的 symbol file (*.pdb) 放在 symbol path 下面。

Symbol path 可以用 _NT_SYMBOL_PATH 這個環境變數來設定:

_NT_SYMBOL_PATH=C:\SymPrivate;SRV*C:\SymServer*http://msdl.microsoft.com/download/symbols

 

重點4:合併完的 merge.etl 如果太大的話,無法成功產生 memory leak 分析報告!

目前我還不知道上限是多少,或者跟電腦的記憶體大小有沒有關係,

像是在我的電腦上,大小在 7~8GB 的檔案都 OK,

但十幾GB的檔案幾乎都無法成功作出 stacks.txt…

因此要特別注意!!

其實這一點很麻煩,導致我必須一直觀察現在的檔案大小有沒有錄太大了…

因此後來寫了一個 AutoIt script 來輔助作這件事情…

下次再來分享囉~~ 🙂

(本頁面已被瀏覽過 186 次)

發表迴響

你的電子郵件位址並不會被公開。

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料