【问题标题】:How do I read a Visual Studio 2019 memory snapshot of my C# service usefully?如何有效地读取我的 C# 服务的 Visual Studio 2019 内存快照?
【发布时间】:2020-02-17 13:28:34
【问题描述】:

我已经阅读了当我询问内存快照时出现的其他问题,但我可能太厚而无法真正掌握它。我有一个 Windows 服务,我可以通过重复执行非常简单的数据操作来产生内存泄漏。我一路上拍摄了内存快照,我看到根的数量正在增加(从成功启动后的 2,100 到 100 次左右的数据操作后的 7,100)。快照是在蓝色箭头标记处拍摄的:

在多次数据操作之前,内存快照是这样的:

之后是这样的:

我们使用 WCF 进行数据传输,看起来序列化在内存增长中发挥了作用,但我不知道从哪里开始。如果我查看RuntimeType+RuntimeTypeCache 的实例,绝大多数实例如下所示:

如果有人可以帮助我确定下一步要采取的措施,我将不胜感激。我们有一个静态实例,它有一个并发字典 ServiceHosts,我对此表示怀疑,但我不知道如何确认。

编辑:

这似乎也很重要,并且参考了ServiceHosts。我们能否通过这种静态关系启用一些不明智的代理生成和实例保留?

【问题讨论】:

  • RunTimeTypeCache 是内部反射,由序列化使用。 stackoverflow.com/questions/3065386/… 你不能改变任何东西。建议在不同的 AppDomain 中运行序列化。 XML 序列化使用动态创建的代码,无法卸载代码。它被重复使用了。所以不应该永远增长。如果你想优化你自己的代码,你应该寻找由你自己的代码创建的东西,你自己创建的类型的对象。
  • 这是对相同数据反复进行的相同数据操作。如果它被重复使用,我应该看不到任何增长,对吧?
  • 它随着使用的类型而增长。如果再次加载相同的对象类型,它不应该增长。如果您需要新的泛型或新的 lambda f.e.,它会增长。你为什么这么在乎?有了 2MBytes 就不用担心了。这个内存视图可以很好地找到您创建的内存泄漏。 - 但你没有泄漏 - 你只是想知道发生了什么好奇。如果您非常频繁地运行此脚本,您可以考虑使用序列化-dll。 stackoverflow.com/questions/934411/… 这样可以避免在每次启动时创建新的 dll。
  • A) 我正在加载相同的类型,但内存占用量在增加,B) 我们在生产服务器上出现内存不足异常,这不仅仅是为了好玩。
  • 但是不要只看这个。查找您的数据对象。这个“OperationDescription”也很大。当内存达到 1GByte(1.000.000.000 Bytes)时检查内存,然后您可以更确定地查看负责的对象。您还可以在两次读取操作之间调用 GC.Collect(),以确保释放任何分配的对象。你确定,你重复使用你的 XmlSerializer 吗?或者你每次都创建一个新的。我知道这更多的是关于序列化,而不是“如何阅读这个窗口”。但是我们无法理解整个 .net 框架说“为什么要分配这个或那个”。

标签: c# memory-management memory-leaks


【解决方案1】:

按大小对您的项目进行排序,并在该列表中注意您自己的类类型。哪一个在堆积。至少总共有几兆字节的对象,以确保看到真正的“堆”,而不仅仅是基础架构的某些部分。

现有的 12.000 种运行时类型,可能表示动态创建的类型,可能会为每个新调用创建序列化 DLL。

您也可以在关键函数调用之后尝试执行 GC.Collect() 来强制垃圾收集。

【讨论】:

    猜你喜欢
    • 2015-08-20
    • 1970-01-01
    • 2016-12-09
    • 2020-11-10
    • 2020-11-07
    • 2020-04-02
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    相关资源
    最近更新 更多