MiniProfiler未正确释放Timings引发内存泄漏问题求助
MiniProfiler中Timings对象无法正常释放引发内存泄漏问题
我在使用MiniProfiler开展性能分析时,发现组件存在无法正确Dispose/释放Timings对象的问题,存在潜在内存泄漏风险。
我使用Jetbrains DotMemory工具在测试工作负载执行前后分别抓取内存快照,发现测试过程中生成的1000个Timings对象始终被MiniProfiler实例持有,无法被垃圾回收。若用户使用该工具分析大量长文本数据库查询等场景,该问题将引发严重的内存占用异常。
最小复现代码如下:
public static void Main() { try { // 在此处抓取第一次内存快照 Console.ReadKey(); var mp = MiniProfiler.StartNew(); var rnd = new Random(); for (int j = 0; j < 1000; j++) { using (mp.Step("outer")) { rnd.Next(); } } Console.WriteLine(MiniProfiler.Current.RenderPlainText()); mp.Stop(true); mp = null; if (Debugger.IsAttached) Console.ReadKey(); // 在此处抓取第二次内存快照 } catch (Exception ex) { Console.WriteLine(ex); } }
感谢各位提供的帮助!
我对问题做了补充,新增更贴近实际场景的复现示例:感谢@Ed Pavlov的解答,但在更复杂的测试场景下Timings对象仍无法被正常释放。第二个示例基于Release配置编译,执行数据库SQL查询逻辑,我特意使用了较长的命令文本以稳定复现该现象:
public static async Task Main() { try { Console.ReadLine(); await DoStuff(); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex); } } internal static async Task DoStuff() { var mp = MiniProfiler.StartNew("Test"); for (int i = 0; i < 5000; i++) { await Test(); if (i % 200 == 0) Console.WriteLine(i); } Console.WriteLine(MiniProfiler.Current?.RenderPlainText()); await mp.StopAsync(true); } public static async Task Test() { var rnd = new Random(); var txt = CommandFacade.CommandText.Replace("@@ID@@", rnd.Next(3000).ToString()); using (MiniProfiler.Current.Step("Level 1")) using (var conn = GetConnection()) using (var cmd = new ProfiledDbCommand(new SqlCommand(txt), conn, null)) { await conn.OpenAsync(); await cmd.ExecuteNonQueryAsync(); conn.Close(); } } public static DbConnection GetConnection() { DbConnection cnn = new SqlConnection(ConnectionString); if (MiniProfiler.Current != null) { cnn = new ProfiledDbConnection(cnn, MiniProfiler.Current); } return cnn; }
新示例对应的dotMemory内存快照包含两类内容:
- DotMemory内存占用概览
- 留存Timings对象的引用链详情
内容的提问来源于stack exchange,提问作者TheMike
相关产品推荐
相关产品推荐

