一:背景
1. 講故事
前幾天寫了一篇 如何洞察 .NET程序 非托管句柄泄露
的文章,文中使用 WinDbg 的 !htrace
命令實現(xiàn)了句柄泄露的洞察,在文末我也說了,WinDbg 是以侵入式的方式解決了這個問題,在生產(chǎn)環(huán)境中大多數(shù)情況下是不能走附加進程的模式,所以這也是它最大的局限性。
那如何以非侵入
的方式解決這個問題呢?這就是本篇討論的重點,對,就是用 CLR 團隊
鼎力推薦的 Perfview 來解決這個問題,哈哈,是我昨天看文檔無意發(fā)現(xiàn)的 ??????。
二:PerfView 分析
1. 測試案例
還是用那一篇文章的例子,讓 C# 和 C++ 交互的時候產(chǎn)生句柄泄露, C++ 代碼如下:
// Example_20_1_5.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
extern "C"
{
_declspec(dllexport) void CSharpCreateEvent();
}
#include "iostream"
#include <Windows.h>
using namespace std;
void CSharpCreateEvent()
{
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
printf("\nEvent句柄值: %#08x ", hEvent);
}
在 C# 中我用 Task 的形式調(diào)用 CSharpCreateEvent
函數(shù)來產(chǎn)生 Event 句柄泄露,參考代碼如下:
internal class Program
{
[DllImport("Example_20_1_5", CallingConvention = CallingConvention.Cdecl)]
extern static void CSharpCreateEvent();
static void Main(string[] args)
{
try
{
while (true)
{
Task.Run(() =>
{
CSharpCreateEvent();
});
Thread.Sleep(10);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
}
2. Handle 分配監(jiān)控
在 perfview 中可以開啟內(nèi)核級別的 OS Handle ETW事件 來進行分配和釋放監(jiān)控,用 +1
和 -1
表示,為了讓事件產(chǎn)生的更少,在 Focus process 中指定 Example_20_1_4.exe
,并且選中 Handle
復(fù)選框,截圖如下:
如果嫌面板太麻煩,可以使用 /KernelEvents:Handle,Default
命令即可,完整的 Command 命令如下:
PerfView.exe "/DataFile:PerfViewData.etl" /BufferSizeMB:256 /StackCompression /CircularMB:500 /KernelEvents:Handle,Default /NoGui /FocusProcess:"Example_20_1_4.exe" /NoNGenRundown collect
接下來點擊 Start Collection
開啟收集,收集一會之后點擊 Stop Collection
,生成好 Zip 之后選擇 Advanced -> Windows Handle Ref Count Stacks
選項,在彈出面板中選擇我們的 Example_20_1_4
程序,刪除 GroupPats
分組信息,處理后的截圖如下:
從上面的面板信息的 Handle Type Event
來看,當(dāng)前有 5445 個 Event 事件沒有被 Close,原來是 Event事件 的泄露哈,接下來在右鍵面板中選擇 Goto -> Item in Callers
選項可以看到每一個 Event 的詳細列表。
最后就是抽選其中幾個,觀察到底是什么代碼創(chuàng)建的 Event ? 截圖如下:
仔細觀察面板信息,可以清楚的看到,原來是 Main
函數(shù)中有一個匿名方法,它在內(nèi)部調(diào)用了 Example_20_1_5!CSharpCreateEvent
方法來創(chuàng)建句柄。
到這里就真相大白了。文章來源:http://www.zghlxwxcb.cn/news/detail-578720.html
三:總結(jié)
通過這個案例可以看到 PerfView 的最大好處就是無侵入性,WinDbg 和 Perfview 真的是一對好搭檔,優(yōu)勢互補。文章來源地址http://www.zghlxwxcb.cn/news/detail-578720.html
到了這里,關(guān)于用 PerfView 洞察.NET程序非托管句柄泄露的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!