.Net7 GC标记阶段代码的改变
前言
由于业务需求,在探究.Net7的CLR,发现了一个不通的地方,也就是通过GCInfo获取到了对象之后。它并没有在GcScanRoots(对象扫描标记)里面对它进行标记,那么如果没有标记这个对象如何被计划阶段构建呢?仔细研读,发现它跟之前的代码之所以不同,是因为它把标记抽取出来,另外形成一个数组循环标记。本篇来看下。
概括
1.问题:
假如说有以下示例代码:
static void Main(string[] args)
{
Console.WriteLine("Tian Xia Feng Yun Chu Wo Bei!\r\n");
Program PM= new Program();
PM = null;
GC.Collect();
}
调用GC.Collect()函数,GC垃圾回收的第一步,就是标记。这个标记实质上可以分为以下几步。
一:获取到所有的线程(GetAllThreadList)
二:遍历循环这些线程的帧
三:通过遍历到的帧,找到这些帧对应的GCInfo
四:通过GCInfo的偏移量和寄存器找到相对应的对象
五:对找到的对象进行标记。
以上四步,基本上没变。第五步标记的时候,它加入了一些新的代码。
uint8_t *mark_queue_t::queue_mark(uint8_t *o)
{
Prefetch (o);
size_t slot_index = curr_slot_index; //这里有一个slot的索引
uint8_t* old_o = slot_table[slot_index];// 这里把这个索引的值从数组取出来
slot_table[slot_index] = o;//把新对象赋值到索引所在的数组内存
curr_slot_index = (slot_index + 1) % slot_count;
if (old_o == nullptr)//这个地方是关键,因为假如说你按照上面的示例代码,之前并没有这个PM对象。所以这个old_o是等于nullptr的,所以它直接return了。那么下面就不存在标记了。问题是这个标记不标记??还是在别的地方标记了??
return nullptr;
BOOL already_marked = marked (old_o);
if (already_marked)
{
return nullptr;
}
set_marked (old_o);
return old_o;
}
二:解决
要解决这个问题,就需要知道数组slot_table里面的数值是何时被变动的。这个其实很简单在VS里面可以,打个条件断点--值更改时中断。
结果发现在函数get_next_marked里面对slot_table数组里面的值(也就是对象)进行了一个标记
uint8_t* mark_queue_t::get_next_marked()
{
size_t slot_index = curr_slot_index; //获取到当前slot_table数组的总数索引
size_t empty_slot_count = 0;
while (empty_slot_count < slot_count) //从零开始循环总数索引
{
uint8_t* o = slot_table[slot_index]; //一个个的取出来,保存到o变量。
slot_table[slot_index] = nullptr; //然后把相应的索引位内存置0,以便下次标记的时候继续使用。
slot_index = (slot_index + 1) % slot_count;
if (o != nullptr) //如果这个o不等于null,那么下面的代码就是对它进行一个标记。
{
BOOL already_marked = marked (o); //判断它是否被标记
if (!already_marked) // 如果没有
{
set_marked (o); // 则对它进行标记
curr_slot_index = slot_index;
return o;//把标记过的对象返回
}
}
empty_slot_count++;//继续循环下一次,继续标记下一个
}
return nullptr;// 如果索引为空,则直接返回null
}
这个函数是被drain_mark_queue函数调用,而前者则是在GCScanRoot整个函数被完成之后调用的。
那么整体的就打通关节了,实质上它是抽取出来了,重新进行了标记。而非在GCScanRoot里面进行标记。
结尾:
作者:江湖评谈。公众号:jianghupt。扫码关注我,带你了解.Net高阶技术。

.Net7 GC标记阶段代码的改变的更多相关文章
- 《垃圾回收的算法与实现》——GC标记-压缩算法
基本算法 Mark-Compact与Mark-Sweep的第一阶段均为标记活跃对象,第二阶段则不同,压缩算法则是将活跃对象逻辑上移到一起. Lisp2算法 对象头中增加forwarding指针,其用法 ...
- 《垃圾回收的算法与实现》——GC标记-清除算法
基本算法 标记-清除算法由 ==标记阶段== 和 ==清除阶段== 构成. 标记即将所有活动的对象打上标记. 清除即将那些没有标记的对象进行回收. 标记与清除 遍历GC root引用,递归标记(设置对 ...
- Java GC 标记/清除算法
1) 标记/清除算法是怎么来的? 我们在程序运行期间如果想进行垃圾回收,就必须让GC线程与程序当中的线程互相配合,才能在不影响程序运行的前提下,顺利的将垃圾进行回收. 为了达到这个目的,标记/清除算法 ...
- 1. GC标记-清除算法(Mark Sweep GC)
世界上第一个GC算法,由 JohnMcCarthy 在1960年发布. 标记-清除算法由标记阶段和清除阶段构成. 标记阶段就是把所有的活动对象都做上标记的阶段. 标记阶段就是"遍历对象并标记 ...
- UIImage扩展用代码直接改变图片大小
以下内容属于转载 在iOS中,uiimage没有用于修改大小的属性,要在代码中改变uiimage图片的大小,需要扩展UIImage类,如下: 头文件: #import<UIKit/UIKit.h ...
- legend3---18、第一阶段代码完成
legend3---18.第一阶段代码完成 一.总结 一句话总结: 看起来麻烦或者自己因为厌烦不想做的,其实硬着头皮来做,一下子就做完了 1.layer_mobile的loading层和关闭loadi ...
- alpha阶段 代码结构及技术难点简介
我们的产品是安卓端app,所以目前主要就是用Android Studio来进行代码开发. Android Studio的项目的结构还是比较清晰的,如下图,主要就是java文件夹内的代码部分(.java ...
- uboot两阶段代码分析
1.启动过程特征总结(1)第一阶段为汇编阶段(start.s).第二阶段为C阶段(board.c中的start_armboot 函数)(2)第一阶段在SRAM中.第二阶段在DRAM中(3)第一阶段注重 ...
- PerfView专题 (第七篇):如何洞察触发 GC 的 C# 代码?
一:背景 上一篇我们聊到了如何用 PerfView 洞察 GC 的变化,但总感觉还缺了点什么? 对,就是要跟踪到底是什么代码触发了 GC,这对我们分析由于 GC 导致的 CPU 爆高有非常大的参考价值 ...
- RxCache 的代码分析,含缓存时间duration的在代码中改变的自己实现的机制
当应用进程创建 RxCache 的实例后,会给应用进程返回一个 rxcache实例及一个 ProxyProvider,代码如下: CacheProviders providers = new RxCa ...
随机推荐
- POJ I Think I Need a Houseboat
I Think I Need a Houseboat 思路:距离问题,一道水题 代码: #include <iostream> #include <cmath> using n ...
- ES6的Map和Set的了解和练习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vscode php 方法无法跳转问题
安装扩展 PHP IntelliSense #路径感知 PHP Intelephense #自动补全 PHP DocBlocker #在类或属性.方法上面敲/**回车自动生成参数注释等 PHP Na ...
- Element-ui树形控件el-tree鼠标移入显示隐藏效果超简单
显示效果: 废话不多说,直接上代码 <template> <el-tree default-expand-all :data="data"> <spa ...
- AirSim 自动驾驶仿真 (2-3) python控制无人机 win10
1首先搭建好环境 参考 2 python控制 https://blog.csdn.net/Zhaoxi_Li/article/details/108002544 官方代码位置 自己pythonj教程 ...
- Leetcode457
A very absurd description for this problem, but people can get the idea by looking at the examples.. ...
- 2022 ICPC沈阳合肥游记
选赛区的时候很争议,除了沈阳是确定要选,队友对于合肥新赛区的看法很质疑,但我想选合肥,一是觉得人少,二是觉得强队会少,因为隔壁CCPC.然后就选了合肥,看情况选合肥确实很对. 一开始也不认为会拿牌,后 ...
- linux一些指令
一. 文件操作命令 查看当前目录下的文件或文件夹 详细查看ls –l 每列代表不同的意义: 第一列drwxr-xr-x 表示权限, n 其中第一个字符d表示 目录(可能有b-块 ...
- BubbleSort,冒泡排序,C++非递归和递归实现
1 // g++ bubble_sort.cc -Wall -O3 && ./a.exe 2 3 4 #include <iostream> 5 #include < ...
- js 将多层json对象 转化为一层json
const parse = data => { const uid = `uid_${Date.now()}`; const process = (input, prefix = '', jso ...