Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET第0代堆大小_.net_Garbage Collection - Fatal编程技术网

.NET第0代堆大小

.NET第0代堆大小,.net,garbage-collection,.net,Garbage Collection,是否可以在.NET中设置0代堆的最小大小 我有如下的情况。我有一个函数,可以分配大约20-30 MB的1KB对象,对它们执行一些操作,然后终止,将所有分配的对象留给GC-ed。现在,在Performance Monitor中,我可以看到第0代堆大小为5-6 MB,这不足以接受我需要的所有20-30 MB对象。当我开始分配时,gen0gc会在某个时候开始运行,因为需要所有的对象,所以它会将它们升级到gen1。下次GC开始运行时,这些对象将在gen2中升级。因此,最终,我的对象中大约有15MB被放入

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


我有如下的情况。我有一个函数,可以分配大约20-30 MB的1KB对象,对它们执行一些操作,然后终止,将所有分配的对象留给GC-ed。现在,在Performance Monitor中,我可以看到第0代堆大小为5-6 MB,这不足以接受我需要的所有20-30 MB对象。当我开始分配时,gen0gc会在某个时候开始运行,因为需要所有的对象,所以它会将它们升级到gen1。下次GC开始运行时,这些对象将在gen2中升级。因此,最终,我的对象中大约有15MB被放入gen2堆中。按照我的逻辑,这些都是临时对象,决不应该出现在gen2堆中。我相信问题在于gen0堆的大小。但我不确定。我知道在Java中有可能设置一个最小的世代堆大小。在.NET中有这样的方法吗?

您确定不再引用这些对象了吗?GC非常善于根据应用程序的需要调整自身,并且不会将对象升级到第2代,除非您在某个地方为这些对象建立了根


我认为,如果您找出这些根的位置,并确保不再在任何地方引用这些对象,那么GC将开始释放这些对象的内存,并且永远不会将它们升级到第1代,更不用说第2代了。此外,如果您这样做,GC将检测到您需要第0代更大,并将代表您增加堆的大小。

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


现在看来,似乎没有一种方法可以通过编程来配置GC生成预算/大小。

不同生成的大小是一个实现细节,我不知道有什么方法可以对.NET应用程序进行调优。如果我的内存正常,那么第0代和第1代共享一个段,在Win32中为16 MB,因此如果您确实创建了大量对象,其中一些对象将被提升到更高的一代,如果它们仍然被引用(正如您所描述的)

我想限制第0代的规模背后的想法是确保g0收集是便宜的。如果第0代可以扩展到任何规模,您的总体性能很可能会受到影响

编辑:我相信杰弗里·里克特(Jeffrey Richter)的书中有一些关于这方面的细节,所以你可能想看看

编辑2:Richter指出(第502-507页),第0代的初始预算为256KB,第1代的初始预算为2MB。然而,这不是一代人的规模。预算会根据需要进行调整,并根据应用程序的内存使用情况进行增减


然而,Joe Duffy的Professional.NET Framework 2.0指出,历代(即第0代和第1代)共享一个片段,通常为16MB(第117页)。只有第2代可以根据需要增长(我假设LOH也可以根据需要增长,但这在文本中我并不清楚)

第0代堆的初始大小为CPU的缓存。这样,小的临时对象甚至不需要移动到主内存。

我认为没有任何选项可以在.NET GC中设置这些值

乍一看,这一特殊情况似乎证明需要有这样的高级选项,但如果这是一个静态选项,它将影响程序的整个生命周期。一个可以在运行时设置的动态选项是理想的

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


由于GC是自调优的,gen(0)将自动增加大小,大对象迟早会被垃圾收集

谢谢你们的帮助

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


这是否意味着,每当我需要一个大小大于85K的临时数组时,该数组将最终位于larget对象堆中?

在第一代时,0可能会增加或减少,但这些都是在将来。当进程运行时,初始化的托管堆在第256KB代中具有固定大小(这意味着Richter),因为现代计算机有256个或更多的内存用于第二级CPU的现金。 第二安德鲁,你说得对。当某个对象太大时,它会立即进入gen2。 我可以假设你想减少gen0的大小,以促使更频繁地调用GC来清除未使用的空间并使你的应用程序更轻。我在SilverLight网站上也遇到了同样的问题,我正在寻找解决方案。我想,如果代码创建了很多有根的对象,当gen0已满时,CLR调用GC将它们移动到gen1,然后当对象增长更多时,将它们移动到gen2,会怎么样。假设这三代人都快吃饱了。然后,例如GC调用。它会做什么。只清楚第0代?第一个和第二个如何。 我认为保持记忆轻松的解决方法如下。首先创建小而多的对象
static void Main(string[] args)
{
     while (true)
     {
         byte[] objects = new byte[100000];
     }
}