.NET中的大型Gen 0堆,浪费内存?

时间:2012-01-06 20:15:53

标签: asp.net .net c#-4.0 memory-management

我有一个使用大量内存的ASP.NET / C#Web应用程序。

ANTS Memory Profiler和PerfMon都显示我的Gen 0堆在Application_Start期间迅速增长到大约1 GB。我读到here,Gen 0 Heap的PerfMon计数器实际上显示了Gen 0的“预算”,而不是大小(我认为并非所有内存都是进程私有工作集的一部分? )。但是ANTS分析器确实显示了大约700 MB的“未使用的内存分配给.NET”,而这个 似乎是该进程的私有工作集的一部分(如taskmgr中所报告的)。我猜这大量未使用的内存与大的Gen 0堆有关。

当发生这种情况时,Application_Start中发生的事情是我在一个while循环中从SqlDataReader读取大约一百万行。这些用于填充大型缓存以供以后使用。鉴于此,大量未使用内存的明显罪魁祸首是大对象堆碎片,但我不认为是这种情况,因为我预先分配的数量超过了我的大型缓存对象所需的数量。可以肯定的是,我甚至尝试将实际添加到缓存对象的循环部分注释掉;它没有分配未使用的内存量。

作为测试,我经常尝试在循环期间强制收集gen 0的垃圾回收(针对所有建议,我知道),这导致gen0堆的大小保持在128 MB左右并且也导致只有少数MB未使用的可用内存。但它也最大化了我的CPU并使Application_Start占用太长时间。

我的问题是:

1)什么会导致Gen 0堆的报告大小变得如此之大?

2)这是一个问题吗?特别是,它是否会导致大量未使用的空间被分配给.NET?

3)如果是这样,我该怎么做才能解决它?如果我无法阻止进程在Application_Start期间使用那么多内存,我希望至少能够在应用程序启动完成时让它放弃内存。

1 个答案:

答案 0 :(得分:4)

Gen 0包含“最年轻,最近分配的对象”,并且与LOH分开且不同。它听起来像是你分配吨和吨的小对象(与那些缓存条目相关的所有勘误表,根据它的声音),它们是无根的(由频繁的GC保持尺寸下降证明)但没有清理及时,因为GC还没有认为有必要。 GC还没有看到清理的必要性。机器有多少RAM?我猜你不是在分页。

我的理解是,当GC认为不再需要时,.NET可以将未使用的堆块返回给操作系统(例如,因为该堆空间已经很长时间没有被使用)。您是否在很长一段时间内观察了应用程序,看看是否会发生这种情况?如果你不是分页,我认为这不是问题。