首页 > 其他分享 >.Net7 GC标记阶段代码的改变

.Net7 GC标记阶段代码的改变

时间:2023-03-17 13:34:47浏览次数:40  
标签:slot index 标记 nullptr marked GC Net7 table

前言

由于业务需求,在探究.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高阶技术。
image

标签:slot,index,标记,nullptr,marked,GC,Net7,table
From: https://www.cnblogs.com/tangyanzhi1111/p/17226410.html

相关文章

  • .Net7 CLR的调用函数和编译函数
    前言.Net运行模型,无非就两个过程。一个是调用入口函数,另外一个就是编译入口函数。前者主调用,后者主编译。概括一:入口函数:RunMainInternal所有的.Net程序,包括控制台,Web......
  • gcc编译报错junk at end of line的原因
    gcc编译的顺序如下: gcc-Ehelloworld.c-ohelloworld.igcc-Shelloworld.i-ohelloworld.sgcc-chelloworld.s-ohelloworld.o必须注意,-E和-S是区分大小写的,......
  • 【洛谷】P2257 YY的GCD(莫比乌斯反演)
    原题链接题意\(T\)组询问,每次询问求:\[\sum_{i=1}^{n}\sum_{i=1}^{m}[\gcd(i,j)\inprime]\]\(T=10^4,n,m\leq10^7\)。思路不难想到枚举质数,将原式化简为:\[\sum......
  • 程序员职业生涯将在 3 年内被AIGC终结,危言耸听还是未来已来?
    近日,前哈佛大学计算机科学教授、谷歌工程主管MattWelsh在美国计算机协会(ACM)的一个虚拟会议上断言:“生成式AI将在3年内终结编程。”Welsh的断言是来自他体验了ChatG......
  • 【AGC】付费下载服务相关问题
     【关键字】付费下载、应用市场、AGC 【问题描述】开发者反馈应用集成了AGC付费下载服务的SDK,在未安装华为应用市场的手机上打开应用时提示要安装应用市场,但是在点......
  • AGC011 题解
    敬告各位:大佬魔怔那叫乐呵,如果实力不够还魔怔那叫小丑。这其实和洛谷灌水区是一个道理,现在灌水区不是流汗就是流汗。虽然有几个真正提问的。[AGC011A]AirportBus普及......
  • SpringCloud+Eureka+Mybatis-Plus+Seata最新搭建
    环境准备1、开发工具:SpringToolSuite42、Spring-Cloud版本:Greenwich.SR23、Seata1.34、Mybatis-Plus5、MysqlSeata简介Seata是一款由阿里巴巴中间件团队发起了开源项目,致......
  • wgcloud详解 - 初始添加ping监测正常,过一会又ping不通的问题
    WGCLOUD有个模块【PING监测】,可以监测各种网络设备、网关、链路是否能正常ping通,如果ping不通说明网络不通,或设备已经下线,系统会发送告警通知提醒我在刚开始添加PING监测后,......
  • centos7.6安装GCC9.3.0
    CentOS7.6下安装gcc9.3.0本文主要介绍怎么在CentOS7.6环境下安装GCC9.3.0,适用于部分源码包需要高版本的gcc进行编译的场景,需要准备的环境有:CentOS7.6gcc-9.3.0.......
  • SpringCloud Alibaba Nacos 简介
    Nocos(DynamicNamingandConfigurationService)一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。可以说Nacos是注册中心和配置中心的组合。Nacos官网;h......