概要
Visual Studio2022のパフォーマンスプロファイラでメモリーリークを調査してみます。
目的
メモリリークの調査時にはこれまで、パフォーマンスカウンターのみを使用していました。
開発環境においては、VisualStudioのパフォーマンスプロファイラの方が手軽に使用できそうだと感じたため、使用感を確かめます。
測定対象プログラムの準備
試しに次のプログラムを実行します。
(現実にはこんなプログラムはありませんが)
internal class Program
{
static void Main(string[] args)
{
for (int i = 1; i < 1000; i++)
{
ManagementClass m = new ManagementClass("Win32_OperatingSystem");
ManagementObjectCollection moc = m.GetInstances();
}
}
}
VisualStudioのパフォーマンスプロファイラからメモリ使用量を測定します
測定結果の分析
ガベージコレクタが動いて定期的にメモリ解放はされていますが、
メモリ解放後の谷の高さが徐々に上昇しています。
同じ処理を繰り返していても、このように谷が上昇する場合は、メモリ解放漏れがあることを推察出来ます。
測定中に2回スナップショットを撮りましたので、差分を確認してみます。
マネージドメモリのスナップショット間での相違は0バイトでした。
「マイコードのみ表示」のチェックを外すと僅かに差異がありますが、16バイトなので谷の高さを押し上げる程のものではなさそうです。_ComObjectが増えているのが気になります。アンマネージドコードの解放漏れがあると推察できます。
ManagementClassクラスを調べると、リソース解放のためのDispose
メソッドがあることから、Dispose
メソッドを呼ぶように変更します。
internal class Program
{
static void Main(string[] args)
{
for (int i = 1; i < 1000; i++)
{
ManagementClass m = new ManagementClass("Win32_OperatingSystem");
ManagementObjectCollection moc = m.GetInstances();
m.Dispose();
moc.Dispose();
}
}
}
メモリ使用量が減り、実行速度も倍以上早くなりました。
雑にタスクマネージャーで比較してみたところ、Dispose
前はWMI関連のプロセスがCPUバウンドで遅くなっていたようです。
感想
手軽に使えて良いですね!
今回はアンマネージドオブジェクトでしたが、マネージドオブジェクトのメモリーリークなら、もっと楽に解決できそう。
補足
UserMarksを使うことでプロセスメモリのチャートにマーカーを置くことが出来ます
using Microsoft.DiagnosticsHub;
var myUserMark = new UserMarks("MyMark");
using (var myRange = new UserMarkRange("MyMethodRange"))
{
}