如果我的Object大于.Net中的Gen 0大小会发生什么?

时间:2018-01-24 11:22:06

标签: c# .net

在采访中,采访者问我以下内容:

  

假设Gen 0的大小为5 kb,而我创建的对象大小为20 kb,会发生什么?

我回答说CLR将扩展Gen 0区域。

现在我很困惑这是否是正确的答案。

这是对的吗?

6 个答案:

答案 0 :(得分:1)

具体细节取决于实现,框架版本之间可能略有不同。 Gen0和Gen1不是为了生长,而Gen2可以无限增长。突破Gen0和1的限制通常会触发一个集合。

  

第1代和第0代存在于称为短暂片段(每个堆中的第一个小对象片段)的东西中,并且第1代和第0代的大小永远不会超过片段的大小。如果创建了将成为新的短暂段的新段。另一方面,Gen 2可以无限增长(或直到你的内存耗尽),所以如果你的内存消耗很高,你的大量对象将会存在于Gen 2中。

根据我对大型ETL过程的经验,大型数据对象往往很快就被分配到Gen2,而Gen2垃圾收集相对不频繁,因此这些对象可以保留一段时间。

文章How does the GC work and what are the sizes of the different generations?概述了这一点以及一些相关链接。

答案 1 :(得分:1)

你最终会得到25K的第0代,除非发生一些疯狂的事情(比如另一个线程分配一堆内存或者因为其他几代人太大而触发GC)。

Gen 0的预算通常远大于25k(默认为256K),因此分配该金额不会做任何特别的事情。对象本身不大于85K,因此它也不会在大对象堆中结束。

数字(5K和20K)有点奇怪,因为它们不会接近任何有趣事件的阈值。

答案 2 :(得分:0)

LOH不等于第2代

大于85K的大多数对象将直接分配给LOH

但是第2代对象可以很小,它只能在第0代和第1代中存活,而且代数也很紧凑。

答案 3 :(得分:0)

我认为Generations中只保存了对象指针,因此无论对象大小有多大,该物理空间的地址都会很小。

答案 4 :(得分:0)

GC在Gen0,Gen1和Gen2代中工作。除此之外,还有LOH用于存储大于85kB的物体。

  1. 每个对象必须进入Gen0,这意味着Gen0更大 超过85kB。如果物体大于85kB,则直接进入LOH。
  2. GC为Gen0,Gen1和Gen2分配初始内存预算 取决于平台,x86或x64 ...但这些数字都很好 已知
  3. Gen0,Gen1和Gen2的大小在运行时可能会因GC而异 试图微调内存消耗并加速GC
  4. 基于这些,如果创建了新对象,如果有足够的预算,它应该输入Gen0。如果没有足够的预算,GC将开始收集。根据Gen0的预算,Gen1和Gen2 GC还将决定运行哪一代产品。在收集期间,将丢弃未引用的对象,并将引用的对象提升为下一代。 GC的目的是尽可能保持Gen0的大小,因为Gen0集合是最常用的,但在某些情况下GC可能会尝试为Gen0分配更多的内存。

      

    让我们假设Gen 0的大小是5 kb,而我的对象是   创造大小20 kb,会发生什么?

    假设5kB是Gen0 GC的空闲内存将开始收集并尝试释放超过20kB(如果可能的话)。如果GC无法回收足够的内存,它将尝试增加Gen0并进行一些收集以回收足够的内存。即使这样,也没有足够的内存OutOfMemoryException将被抛出。

答案 5 :(得分:-2)

大型物体将跳过第0代和第1代。

  

将小型.NET对象分配到Small Object Heaps(SOH)上。

     

...

     

大于85 KB的对象被分配到大对象堆(LOH)上。由于复制大块内存的开销,它们不会被压缩。当发生完整的GC时,未使用的LOH对象的地址范围将被记录在可用空间分配表中。

Source: red-gate article on .NET memory management

  

新分配的对象形成新一代对象,并且隐式生成0集合,除非它们是大对象,在这种情况下它们会在第2代集合中的大对象堆上进行。

Source: MS docs on GC