在CLR探索系列的研究DotNet下的垃圾回收器这几个博文里,就先说说GC Heap结构吧,至于垃圾回收的详析算法实现,以后再写了。
在一个托管进程被创建以后,在托管进程的内存空间里面,包含了System Domain,Shared Domain,Default Domain,以及一系列的Heap,有Process的Heap,JIT Code Heap,GC Heap以及LOH。
在DotNet的CLR的实现中,GC heap和LOH(Large Object Heap)是包含在一个类里面实现的。这就造成了在内存中,一个GC Heap后面紧跟着的就是LOH Heap。在实现的时候,一个gc_heap类里面包含了一个GC的结构类,以及一个LOH。
一个GC Heap的结构大致如下:
上面是一个GC Heap的大致结构。从上面到下面是从低地址到高地址。有的时候,需要找一个需要的存在了很久的Object的时候,并不是往高地址去寻找,也有可能存在于低地址区域,这个和每个Generation的大小的动态改变有关。
说到这里,就会提到一个非常有趣的概念,“策略”。这个是GC开发小组的开发人员在研究呢很久性能和用户的操作以及内存管理之间的平衡只会整出来的一个比较有趣的概念。在垃圾回收的过程中加入了“策略”。譬如一个Generation 0代占有256KB的内存大小,如果在实际的程序的运行过程中发现新对象的创建特别频繁,那么GC EE就会自动增加这个Generation 0的大小。
在说明一个GC Heap的结构的时候,先用windbg+sos来看看一个用户态运行的程序的GC Heap里面都有些啥:
0:003> !eeheap
=======================================
Number of GC Heaps: 1
generation 0 starts at 0x00ca1018
generation 1 starts at 0x00ca 100c
generation 2 starts at 0x00ca1000
ephemeral segment allocation context: none
segment begin allocated size
00161e00 790d5588 790f 4b38 0x 0001f 5b0(128432)
00ca0000 00ca1000 00ca3ff4 0x00002ff4(12276)
Large object heap starts at 0x01ca1000
segment begin allocated size
01ca0000 01ca1000 01ca3250 0x00002250(8784)
Total Size 0x 247f 4(149492)
------------------------------
GC Heap Size 0x 247f 4(149492)
=======================================
可以看到,在上面显示的GC Heap的结构中,一个GC Heap里面有两个Heap Segment,紧接着Heap Segment的,是LOH。
在上面的一个GC Heap中,分成三个Generation,最年轻的Object在G 0中。这些Generation是保存在一个一个的Heap Segment里面的。一个Heap Segment可以包含两个Generation或者三个,或者更多。而一个Generation可以跨越多个Heap Segment。
一个GC Heap主要有一个或者是多个Heap Segment组成。然后在GC Heap的最后还有一个保留区域,用来保存一些比较特别的Object。