【问题标题】:XmlSerializer.FromTypes producing memory leaks?XmlSerializer.FromTypes 产生内存泄漏?
【发布时间】:2016-10-18 16:43:12
【问题描述】:

根据MSDN XmlSerializer Class 部分“动态生成的程序集”,XmlSerializer 在使用某些构造函数时会产生内存泄漏。我想知道

XmlSerializer.FromTypes(Type[])

方法也会产生内存泄漏?

编辑:

我在使用FromTypes 方法时遇到了内存问题。所以我开始了一些调查:

for (int i = 0; i < 1000; i++)
{
    DummyObject content = new DummyObject()
    {
        Age = 29,
        Location = "London",
        Name = "Pete"
    };
    XmlSerializer serializer = XmlSerializer.FromTypes(new[] { content.GetType() })[0];
    using (TextWriter textWriter = new StreamWriter($@"D:\test\array\{i}.xml"))
    {
        serializer.Serialize(textWriter, content);
    }
}

多次执行上述代码后,Visual Studio 2015 的诊断工具显示如下:

Diagnostic Tools Image

垃圾收集器运行,但动态生成的程序集似乎正在充斥内存。知道FromTypes 方法在内部使用哪个构造函数会很有趣。那么,FromTypes 方法也会产生内存泄漏?

【问题讨论】:

  • 您是否在使用这种特定方法时遇到了特定问题?还是这只是假设的打蜡?
  • 我在使用这种方法时遇到了内存问题。我在这篇文章中添加了一些代码和 Visual Studio 诊断工具的结果以显示行为。该方法似乎会产生内存泄漏。

标签: c# .net memory-leaks xmlserializer


【解决方案1】:

我稍微更改了您的代码 - 运行循环 3000 次而不是 1000 次,并将序列化数据写入内存流而不是文件,并使用 dotMemory 对其进行分析。 (我使用 VS 发现 RuntimeType 实例被泄露,但没有找到如何查看它们的创建位置)。

最终应用程序占用了大约 1Mb 的内存(我没有收到您屏幕截图中 500Mb 的结果),但这显然是这里的泄漏。

然后打开在 Gen2 堆中的第一个和第四个快照之间创建的所有新对象,发现它们中的大多数(如上所述)是 RuntimeType 的实例。

打开它们,发现它们有五个大小几乎相等的组。

所以,答案是“是的,这种方法会产生内存泄漏”

在分配这些对象的五个堆栈跟踪下方

--------- 1 -------------- 已分配:2985 个对象中的 83580 B

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationWriterILGen.GenerateEnd() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() 折叠物品 [AllThreadsRoot]

------ 2 -------------- 已分配:2984 个对象中的 83552 B

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationReaderILGen.GenerateEnd() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() 折叠物品 [AllThreadsRoot]

--------- 3 -------------- 已分配:2984 个对象中的 83552 B

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateBaseSerializer() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() 折叠物品 [AllThreadsRoot]

--------- 4 -------------- 已分配:2984 个对象中的 83552 B

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateTypedSerializer() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() 折叠物品 [AllThreadsRoot]

--------- 5 -------------- 已分配:2984 个对象中的 83552 B

System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() System.Xml.Serialization.XmlSerializationILGen.GenerateSerializerContract() System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly() 折叠物品 [AllThreadsRoot]

【讨论】:

  • 感谢您的回答!这证实了我对这种方法的怀疑。现在我正在缓存 XmlSerializer 实例,以重用它们并且不会淹没内存。
猜你喜欢
  • 2016-07-15
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 2015-05-03
相关资源
最近更新 更多