.NET 4 WCF 内存问题

Wil*_*rno 5 .net wcf garbage-collection memory-management

我遇到的问题是,我的ASP.NET 4 MVC 2 + WCF应用程序在负载测试期间使用Windows 2008 64 位应用程序中的大量内存,运行几分钟后它将耗尽几乎所有可用内存(8 GB) (我们做了有几个工作进程在运行)。

使用ANTS Memory Profiler进行分析后,它显示了一些有趣的结果:

  1. .NET 托管内存从 15 MB 增加到 40 MB,但这归因于我们在程序中所做的缓存机制。然而.NET本身分配了近180 MB的可用空间,这是出乎意料的。
  2. 非托管内存大小显着增加,直到负载测试运行大约 3 分钟后达到 120 MB(尽管我们的应用程序没有显式使用任何 P/Invoke 或 COM 对象。但是,我们确实使用了一些 COM+ 对象,这些对象在finally 中使用后被释放)堵塞)。
  3. 记忆变得支离破碎。
  4. 上面的第 1 和第 2 项导致整个应用程序在负载测试运行几分钟后使用大约 350 MB ,但如果我们不停止测试,它将继续进一步增长。

根据上面的第1项,我测试了一些应用程序来测试问题是否是由于我们的应用程序或WCF引起的。测试应用程序只是将 XML 数据(约 300KB)加载到多线程应用程序中的数据集。当逻辑存储在 EXE 程序中时,应用程序在完成后仅使用 24 MB 专用字节中的 200 KB(从开始时额外使用 120 KB,其中 40 KB 用于未使用的内存)托管内存(这是可以接受的);但是当逻辑托管在 WCF 中时,应用程序使用 66 MB 托管内存(从 64 MB 空闲/未使用的托管内存开始额外使用 61 MB)。所以看来 WCF / ASP.NET 是导致内存增加很多的原因)。

  1. 为什么.NET 在堆中分配如此多的可用空间?据了解,可用空间可能是在内存快照过程中进行 GC 的某些 Gen 0/Gen 1/Gen 2,但我认为应用程序并没有真正使用那么多内存。
  2. WCF 的行为是否正常?如果是,有什么方法可以改变行为以使其使用更少的内存?
  3. 如何找到非托管内存泄漏,特别是我没有显式使用非托管代码?

感谢您对上述问题的建议。

提前致谢,

威利

Pan*_*vos 5

WCF 使用临时缓冲区来处理消息。您认为的内存泄漏可能是尚未收集的临时缓冲区。

为避免始终创建新缓冲区,WCF 使用BufferManager重用缓冲区,最高可达maxBufferPoolSize (链接到此处的元素)指定的限制,默认情况下为 512KB。任何超出此限制的请求都会导致创建新的缓冲区,这些缓冲区永远不会重用,并且必须进行垃圾收集。

另一个要检查的选项是 maxBufferSize,它限制 BufferManager 可以返回的最大缓冲区大小。较大的缓冲区不会被池化,并且必须被垃圾收集。如果您使用大消息,则可以通过增加此属性来减少临时缓冲区。

尝试增加maxBufferPoolSize看看是否可以减少内存使用。我强烈建议不要最大化它,因为池中的缓冲区永远不会释放,直到应用程序域(即应用程序池)回收。高流量时期可能会导致大量内存被使用但从未被释放。