C# OpenXML 内存泄漏
C# OpenXML memory leak
我注意到我的应用程序中存在内存泄漏并试图找出它。我不知道好的和免费的内存泄漏发现技术(有什么建议吗?)所以我让它变得简单 - 插入内存使用打印(有和没有 GC)然后深入挖掘最大泄漏的地方。可修复的 我已经修复了,但有些我不能,因为它们在包装内。就像这个非常简化的
using System;
using System.Threading;
using DocumentFormat.OpenXml.Packaging;
namespace WorkTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("0) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
Console.WriteLine("Start");
Console.WriteLine("1) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
using (WordprocessingDocument wordPackage = WordprocessingDocument.Open(@"c:\tmp\a.docx", true))
{
// This is Open XML Format SDK 2.5 - v4.0.30319
// It does nothing within this particular block/example
}
Console.WriteLine("2) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
Console.WriteLine("End");
Console.WriteLine("3) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
}
}
}
通常它会产生类似
的东西
0) 000,215,984
Start
1) 000,218,528
2) 000,325,472
End
3) 000,325,472
从小泄漏开始 - 步骤 0-1 是简单输出。它吃的不多。只有 3K,但它仍然是一些东西。步骤 2-3 相同,但它不吃任何东西。
好的。我同意。一些 IO 包可能需要一些内存。不好理解。
第二个-步骤1-2不是那么好理解的。 "Using" 甚至单独的块 {} 也应该完全自行清理。他们没有。甚至更糟。这个例子被简化了。实际上,每次我在我的方法中执行这段代码时,内存都消失了。在这个例子中它是 90K。 100 个文件后是 9Mb。
通过所描述的方法,我还发现调用 GC 时我的应用程序中有几个地方会消耗并且不会 return 内存。每次调用 GC 的唯一结果是 4K 内存消失了。不幸的是我不能在简单的例子中重现它。
到目前为止我只找到了一个解决方案 - 当内存变得关键时我重新启动我的应用程序。不是很好的解决方案,但我找不到更好的解决方案。
好吧,如果我们坚持免费或者我们在生产环境中,我会使用 ADPlus
来创建内存转储并使用 WinDbg
来分析它。您可以 Google 周围有大量关于该主题的知识。
但更简单的方法是在您的应用程序处于 运行 时附加内存分析器。我使用的分析器是商业的,但在 Visual Studio 2013 中也有一个内置的内存分析器。转到 ANALYZE -> Performance and Diagnostics 和 select .NET 内存分配。
我注意到我的应用程序中存在内存泄漏并试图找出它。我不知道好的和免费的内存泄漏发现技术(有什么建议吗?)所以我让它变得简单 - 插入内存使用打印(有和没有 GC)然后深入挖掘最大泄漏的地方。可修复的 我已经修复了,但有些我不能,因为它们在包装内。就像这个非常简化的
using System;
using System.Threading;
using DocumentFormat.OpenXml.Packaging;
namespace WorkTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("0) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
Console.WriteLine("Start");
Console.WriteLine("1) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
using (WordprocessingDocument wordPackage = WordprocessingDocument.Open(@"c:\tmp\a.docx", true))
{
// This is Open XML Format SDK 2.5 - v4.0.30319
// It does nothing within this particular block/example
}
Console.WriteLine("2) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
Console.WriteLine("End");
Console.WriteLine("3) " + System.GC.GetTotalMemory(true).ToString("000,000,000", Thread.CurrentThread.CurrentCulture));
}
}
}
通常它会产生类似
的东西0) 000,215,984
Start
1) 000,218,528
2) 000,325,472
End
3) 000,325,472
从小泄漏开始 - 步骤 0-1 是简单输出。它吃的不多。只有 3K,但它仍然是一些东西。步骤 2-3 相同,但它不吃任何东西。 好的。我同意。一些 IO 包可能需要一些内存。不好理解。
第二个-步骤1-2不是那么好理解的。 "Using" 甚至单独的块 {} 也应该完全自行清理。他们没有。甚至更糟。这个例子被简化了。实际上,每次我在我的方法中执行这段代码时,内存都消失了。在这个例子中它是 90K。 100 个文件后是 9Mb。
通过所描述的方法,我还发现调用 GC 时我的应用程序中有几个地方会消耗并且不会 return 内存。每次调用 GC 的唯一结果是 4K 内存消失了。不幸的是我不能在简单的例子中重现它。
到目前为止我只找到了一个解决方案 - 当内存变得关键时我重新启动我的应用程序。不是很好的解决方案,但我找不到更好的解决方案。
好吧,如果我们坚持免费或者我们在生产环境中,我会使用 ADPlus
来创建内存转储并使用 WinDbg
来分析它。您可以 Google 周围有大量关于该主题的知识。
但更简单的方法是在您的应用程序处于 运行 时附加内存分析器。我使用的分析器是商业的,但在 Visual Studio 2013 中也有一个内置的内存分析器。转到 ANALYZE -> Performance and Diagnostics 和 select .NET 内存分配。