首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MiniProfiler不处理时间

MiniProfiler不处理时间
EN

Stack Overflow用户
提问于 2022-06-14 10:01:45
回答 2查看 92关注 0票数 1

我注意到,MiniProfiler在某种程度上没有释放/释放可能导致内存泄漏的时间。

我使用Jetbrains的DotMemory在工作负载前后进行快照。所有1000个时间仍然保留在MiniProfiler的一个实例中,我似乎无法摆脱这个实例。

这可能会导致相当多的问题,例如,某些人会分析他的数据库查询,这些查询可能有相当长的时间。

最低限度-例如:

代码语言:javascript
复制
public static void Main()
    {
        try
        {
            //Snapshot here
            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();
                //Snapshot here
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

谢谢你的帮助!

又一个例子编辑了我的问题。谢谢@ example,但是一旦我创造了一个更大的例子,时间仍然会继续。下一个示例是使用Release构建的,并针对数据库执行查询。(我特意选择了一个相当大的命令文本来演示这一现象)

代码语言:javascript
复制
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概览截图

保留对象的截图

EN

回答 2

Stack Overflow用户

发布于 2022-06-14 17:52:57

尽管当应用程序在"Debug“配置中构建w/o优化时,将变量"mp”设置为null,编译器仍然生成将所有对象保存到方法末尾的代码。正如您在屏幕截图中所看到的,MiniProfiler和所有定时实例都由局部变量保存在内存中。

在“释放”配置中构建应用程序,或者更好地将代码提取到单独的方法中,以便更好地模拟真实的代码,在方法调用之后,您将看到内存中没有这些对象。

代码语言:javascript
复制
public static void Main()
{
  //Snapshot here
  Console.ReadLine();

  Isolate();

  Console.WriteLine("Ready");
  Console.ReadLine();
  //Snapshot here
}

private static void Isolate()
{
  try
  {
    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;
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
  }
}

票数 0
EN

Stack Overflow用户

发布于 2022-07-07 01:22:24

我对此的再现表明,异步/等待的使用是捕获执行上下文,它保持对MiniProfiler内部使用的MiniProfiler字段内的值的引用。

问题不是缺乏处理,也不是MiniProfiler没有释放时间。Timing只是一次性的,这样就可以方便地限定作用域了。实际的Timing.Dispose方法只是Timing.Stop

查看顶级的Timing实例,会发现它被保存在ExecutionContext上,当我进一步挖掘时,似乎是由于围绕着SQL方法的异步/等待而被实例化了。当我切换到同步等价物时,所有的时间都会得到GC,用一个简单的await Task.Delay(1)替换SQL逻辑也会复制原来的问题。

我稍微打探了一下,如果MiniProfiler做了类似于这里的操作,这看起来可能会有所缓解,但我不知道这个问题有多大,因为我的测试表明,对DoStuff的许多调用不会增加剩余的内存消耗,因为只保留了最后一个分析器。

(用.NET 6和MiniProfiler 4.2.55测试)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72615050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档