9

.NET GC 精要(五)

 3 years ago
source link: https://blog.csdn.net/tkokof1/article/details/104130213
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

.NET GC 精要(五)

本文讲述了 .NET GC 的一些细节知识,内容大部分来自于书籍 Under the Hood of .NET Memory Management
(注:本文假设你了解 .NET 的基础知识,譬如值类型,引用类型等)

之前讲过 .NET GC 出于效率等因素的考虑,对 SOH(Small Object Heap)进行了分代处理(Gen 0, Gen 1 和 Gen 2),当时只是大概讲述了一下基本思路,实际上还有一个细节没有提及(以下说明仅以 Gen 0 回收为例, Gen 1 回收可以直接类比):

.NET GC 进行 Gen 0 回收时,同样是从 GC roots(GC 根)开始遍历标记对象的,但是当发现遍历到的对象是 Gen 1 或者 Gen 2 对象时,就会直接忽略该对象,转而继续遍历标记其他对象,这样 GC
就可以只处理 Gen 0 内存区域中的对象,而不用处理 Gen 1 和 Gen 2 内存区域中的对象.

但是这样做有个前提条件,就是 Gen 1 或者 Gen 2 中的对象不存在对 Gen 0 中对象的引用,否则上述的遍历标记流程就是不完备的,会导致存在引用关系(被 Gen 1 或者 Gen 2 对象引用)的 Gen 0 对象被错误清理回收.

为了解决这个问题, .NET 引入了一个被称为 Card Table 的数据结构(Card Table 其实也可以看做是 GC roots 之一)

细节上, Card Table 实际上类似于一个位图(bitmap),每一位代表 128 字节的内存范围, 如果对应位为 1,则在 Gen 0 回收时, GC 的对象遍历标记流程就会考虑该内存范围内的对象,而 Card Table 的更新则是在 .NET 创建引用时进行,该过程也被称为写入屏障(write barrier).

示意图如下:

在这里插入图片描述

(内存区域 0 - 127 中的对象(即 Object B)会在 Gen 0 回收时进行"额外"的遍历标记)

未完待续(to be continued)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK