.NET生成0堆大小

时间:2009-05-07 11:03:01

标签: .net garbage-collection

是否可以在.NET中设置第0代堆的最小大小?

我有一个下面的sistuation。我有一个函数,分配大约20-30 MB的1KB对象,对它们做一些事情,然后终止,让所有分配的对象都被GC编辑。现在,在性能监视器中,我可以看到第0代堆大小是5-6 MB,这还不足以接受我需要的所有20-30 MB的对象。当我开始分配时,gen0 GC开始运行,并且因为需要所有对象,所以它们将它们提升为gen1。 GC下次开始运行时,这些对象将在gen2中升级。所以最终大约15MB的对象最终进入gen2堆。根据我的逻辑,这些是临时对象,绝不应该在gen2堆中结束。我相信问题在于gen0堆大小的大小。但我不确定。我知道在Java中有可能设置最小的代数堆。在.NET中有这样的方法吗?

7 个答案:

答案 0 :(得分:8)

不同代的大小是一个实现细节,我不知道有任何方法可以为.NET应用程序调整它。如果我的内存正确地为我提供了代码0和1共享一个单独的段,在Win32中是16 MB,所以如果你创建了很多对象,如果它们仍被引用,其中一些将被提升为更高代(如同你描述)。

我想限制第0代大小的想法是确保g0集合便宜。如果0代可以增长到任何规模,那么你的整体表现很可能会受到影响。

编辑:我相信Jeffrey Richter的书中有一些关于此的细节,所以你可能想要检查一下。

EDIT2:Richter声明(第502-507页)第0代初始预算为256 KB,第1代初始预算为2 MB。但是,这不是一代人的规模。预算会根据需要进行调整,并根据应用程序的内存使用量增长和缩小。

然而,Joe Duffy的Professional .NET Framework 2.0指出,ephermal世代(即gen 0和1)共享一个段,通常为16 MB(p.117)。只有第2代允许根据需要增长(我认为LOH也可以根据需要增长,但我不清楚这一点)。

答案 1 :(得分:3)

您确定不再引用这些对象吗? GC 非常 善于根据应用程序的需要进行调整,并且不会将对象提升为第2代,除非您在某处拥有这些对象的根。

我认为如果你弄清楚这些根源在哪里,并确保你真的不再在任何地方引用这些对象,那么GC将开始释放这些对象的内存,并且永远不会将它们推广到第1代,更不用说第2代了。你这样做,然后GC将检测到你需要更大的第0代,并代表你增加堆的大小。

答案 2 :(得分:3)

第0代堆的初始大小是CPU的缓存大小。这样就不需要将小的临时对象移动到主存储器中。

答案 3 :(得分:3)

谢谢你们的帮助。

Wheell,情况非常有趣。我从来没有提到我将这些30MB的对象存储在一个大小为100000的数组中。我首先分配该数组,然后用对象填充它。由于该数组大于85K,因此该数组存储在Large Objects Heap中。事实证明,对于垃圾收集来收集该堆中的对象,它需要运行gen2集合,因此每当Large Objects Heap中没有足够的空间时,它就会运行gen2收集器,这会破坏性能。这是一个简单的例子,它将不断调用gen2集合。您需要在调试模式下运行它(因为编译器优化)。

static void Main(string[] args)
{
     while (true)
     {
         byte[] objects = new byte[100000];
     }
}

这是否意味着每当我需要一个大小超过85K的临时数组时,该数组最终会出现在bigt对象堆中?

答案 4 :(得分:2)

第一代0可能会增加和减少,但这些是将来的。当进程运行时,初始化的托管堆在generation0 256 KB(这意味着Richter)中具有固定大小,因为现代计算机具有256个或更多内存用于第二级CPU的现金。 第二。安德鲁,你是对的。当某个对象太大时,它会立即转到gen2。 我可以假设你想减少gen0大小以激发更频繁的GC来清除未使用的空间并保持你的应用程序更轻。我在SilverLight网站上遇到同样的问题并搜索解决方案。我想如果代码创建了很多具有根的对象,并且当gen0是完整的时,CLR会调用GC将它们移动到gen1,然后当对象增长时,将它们移动到gen2。让我们说所有3代都差不多满了。然后例如GC呼叫。它会做什么。刚清楚一代0?如何使用第一和第二。 我认为sollution保持记忆光是如下。首先创建小而多的对象,而不是大而且数量少。第二个对象内部引用必须是单向的,而不是相互引用的混乱。不是动态创建的静态对象,例如根据来自数据库的提交记录,需要保留在全局变量中,而不是在代码归结时再次创建。

答案 5 :(得分:1)

给安德鲁+1。 GC 自我调整它可以即时了解应用程序的内存需求模式 在您的情况下,如果GC执行Gen 0的集合并发现很多对象幸存/没有回收大量内存,垃圾收集器将自动增加Gen 0预算/配额。

查看GC Type members,似乎没有办法以编程方式配置GC生成预算/大小。

答案 6 :(得分:0)

我认为在.NET GC中设置这些值没有任何选择。

乍一看,看起来这种特殊情况证明需要有这样的高级选项,但如果这是一个静态选项,它会影响所有生命周期你的程序。您可以在运行时设置的动态选项非常理想。

此外,我认为这不会对您的程序性能产生巨大影响,但如果您能够增加gen(0)大小,则可以释放一些内存(并获得某些性能)。

由于GC是自调整的,因此gen(0)会自动增加大小,而 BIG 对象迟早会被垃圾回收。