.NET进程内存使用量= 5x CLR堆内存?

时间:2012-04-12 10:40:11

标签: .net memory process clr heap

我正在努力解决一些内存使用问题。总体而言,我的应用程序收集了一些数据值,并使用C1 WPF图表和数据网格将其可视化,最终将所有内容都放入PDF报告中。

使用YourKit分析我的进程我面临的情况是,CLR堆大小约为120MB(这很好),而进程内存大小约为580MB。这几乎是我实际CLR堆大小的内存消耗的5倍。我的CLR峰值大小为220MB,而710MB进程内存分配。

我很清楚我的对象堆,堆栈等需要一些开销。在Java JVM中,我习惯的典型因素是大约1.5倍。

如何解释这种过多的内存开销?进程只是分配空闲的备用堆空间吗?如果是,这是否解释了710MB与220MB?

2 个答案:

答案 0 :(得分:11)

这里还有一些补充说明。虽然我不太明白你的意思是“CLR堆大小”。 CLR使用了大约8种不同的堆 - 因此您在堆大小与VM大小中看到的内存占某些的差异:

  1. Loader Heap:包含CLR结构和类型系统
  2. 高频堆:静态,MethodTables,FieldDescs,界面图
  3. 低频堆:EEClass,ClassLoader和查找表
  4. Stub Heap:CAS,COM包装器,P / Invoke
  5. 的存根
  6. 大对象堆:需要超过85k字节的内存分配
  7. GC堆:用户为应用分配了专用的堆内存
  8. JIT代码堆:由mscoreee(执行引擎)分配的内存和托管代码的JIT编译器
  9. 进程/基本堆:互操作/非托管分配,本机内存等
  10. 可能导致内存使用过多的另外两个项是内存碎片(主要发生在LOH或大对象堆上)或大量线程。

    内存碎片有很多原因,排除这种情况的最佳方法是使用WinDbg分析GC堆上每个段的段大小。

    对于大量线程,您为应用程序使用的每个线程分配了1MB的堆栈空间。此内存放在Process / Base堆中。因此,如果你有100个线程,你将有额外100MB的内存使用。

    HTH

答案 1 :(得分:2)

如果托管堆的总大小明显小于应用程序使用的专用字节,则可能是您正在分配非托管内存并且(可能)未正确处理它。实现IDisposable的图形对象,流和其他对象需要在它们超出范围之前调用它们的Dispose()方法,或者放在using(){}语句中,以便清除任何非托管资源。使用像ANTS Memory Profiler这样的工具可以向您展示如何分配内存以及哪些对象实现IDisposable。