7

.NET GC 精要(四)

 3 years ago
source link: https://blog.csdn.net/tkokof1/article/details/104112363
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 精要(四)_tkokof1的专栏-CSDN博客

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

之前在讲述 GC 分代回收的时候,我们只是了解了一下 SOH(Small Object Heap) 相关的内存回收行为,实际上,在进行 Gen 2 GC(也称为 full GC)时, GC 流程同样会回收 LOH(Large Object Heap)的内存,只是在方式方法上, LOH 的内存回收和 SOH 的内存回收有很大不同.

首先, LOH 的内存分布比较"直白",并没有 SOH 中所谓的分代概念(Gen 0, Gen 1 和 Gen 2).

再者, 由于 LOH 存储的是大于等于 85000 字节的大对象,所以复制移动这些对象的成本很高,所以, LOH 也并不会进行内存压缩(SOH 对各个分代都会进行内存压缩).

在(大)对象的申请与释放(即 Gen 2 GC)过程中, LOH 会将各个可用的内存区域记录到一个被称为 Free Space Table 的表中:

![]

在申请(大)对象时, .NET 会首先检查 Free Space Table,如果发现有足够的可用内存,则会将(大)对象分配到对应的可用内存区域中,并更新 Free Space Table,如果找不到足够的可用内存, .NET 会将(大)对象分配到当前的堆尾 (有可能会申请新的内存).

![]

(图中 Object E 被分配到了堆尾,即 Object D 之上)

出于性能考虑, .NET 更偏向于将对象分配至堆尾(当然,这种偏向也会导致 LOH 出现更多的内存碎片)

另外值得一提的是, LOH 存储的对象其实也并不都大于等于 85000 字节,对于一些内部数组,譬如 double 数组,由于 1 个 double 占据 8 个字节,似乎 double 数组的长度要大于等于 10625(85000 / 8)(此处我们忽略 double 数组的一些额外存储消耗)才会存储于 LOH 中,但实际上,仍然是出于性能考虑,大于等于 1000 长度的 double 数组就会存储于 LOH 中(不同类型数组的相关阈值也有所不同).

未完待续(to be continued)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK