【发布时间】: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