前言:

很多书籍或者很多文章,对于CLR或者GC这块只限于长篇大论的理论性概念,对于里面的如何运作模式,却几乎一无所知。高达近百万行的CPP文件,毕竟读懂的没有几个。以下取自CLR.Net 6 PreView版本

分配量超过阈值

GC触发里面有一个GC被触发的条件是,分配的内存块超过阈值。这个阈值是在Generation代里面的static_data里面的存储的固定数值。当你分配的内存块超过这个阈值的时候,就会触发GC进行垃圾回收。来看看这个阈值动态加载和超过阈值触发GC垃圾回收之后,重新计算阈值的算法。

初始化

在CLR启动的时候,会初始化Generation的静态数据,此时会填充阈值。

Generation的部分静态数据结构:

struct static_data
{
size_t min_size; 阈值的下限
size_t max_size; 阈值的上限
size_t fragmentation_limit; 碎片空间的上限
float fragmentation_burden_limit; 碎片空间百分比的上限
float limit; 限度的下限
float max_limit; 限度的上限
uint64_t time_clock;
size_t gc_clock;
};

下面是GC定义的初始化参数数值,以上面的结构参考下面:

static static_data static_data_table[latency_level_last - latency_level_first + 1][total_generation_count] =
{
{
// gen0
{0, 0, 40000, 0.5f, 9.0f, 20.0f, (1000 * 1000), 1},
// gen1
{160*1024, 0, 80000, 0.5f, 2.0f, 7.0f, (10 * 1000 * 1000), 10},
// gen2
{256*1024, SSIZE_T_MAX, 200000, 0.25f, 1.2f, 1.8f, (100 * 1000 * 1000), 100},
// loh
{3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0},
// poh
{3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0},
}
}

直接套用:

0代: 阈值下限0,无限制,限度下限9,限度上限20
1代: 阈值下限160kb,无限制,限度下限2,限度上限7
2代: 阈值下限256kb,无限制,限度下限1.2,限度上限1.6

这是最初始化的值,什么意思呢?简而言之,就是CLR在加载此初始化的值的之后,进行了动态的分配的阈值的上下限。也就是说实际上GC的阈值和这里面表明的静态数值有差别。

下面计算均为函数init_static_data里面

0代阈值的下限动态计算方式(以工作站模式为例):

1.通过gc的配置文件(gcconfig)来获取配置文件里面配置的值,如果获取此值失败则跳转到第二步
2.通过windows API GetLogicalProcessorInformation获取到你当前电脑处理器最大的缓存值。
3.下面就是GC第0代阈值的算法了
0代阈值下限= = max((4*你当前电脑处理器最大缓存值/5),(256*1024))
你当前电脑处理器最大缓存值 = max(你当前电脑处理器最大缓存值, (256*1024))
while(如果0代阈值下限*处理器个数>你当前堆分配物理内存总大小/6)
{
0代阈值下限 = 0代阈值下限/2
if(0代阈值下限 <=你当前电脑处理器最大缓存值 )
{
0代阈值下限 = 你当前电脑处理器最大缓存值
}
}
if( 0代阈值下限 > = 小对象堆段(SOH)/2)
{
0代阈值下限 = 小对象堆段(SOH)/2
}
0代阈值下限 = 0代阈值下限 / 8 * 5;// 到了这里才是最终第0代阈值的下限,而非上面generaton的静态数据static_data_table里面的下限阈值为0.

第0代阈值的上限呢?(此处同时看下服务器模式和工作站模式)

服务器模式0代阈值上限的算法:
0代阈值上限=max (6*1024*1024, min ( Align(soh_segment_size/2), 200*1024*1024))
工作站模式0代阈值上限的算法
0代阈值上限= max (0代阈值的下限,0代阈值的上限)
0代阈值上限 = Align (0代阈值的下限)

第1代阈值的上限(服务器模式和工作站模式)

第1代阈值的下限是160kb,那么上限呢?
服务器模式1代阈值的上限=max (6*1024*1024, Align(小对象堆的大小/2));
工作站模式1代阈值的上限=gen1_max_size = Align (服务器模式1代阈值的上限/0)

阈值上限的重新计算

当阈值上限的剩余空间不足以容纳当前CLR分配的内存块的时候,就造成了GC。GC之后,就会重新计算这个阈值的上限。这里是算法

if(GC开始前存活的对象为0)
{
阈值的上限 = 当前代的阈值下限
}
else
{
if(当前代 >= 第二代)
{
cst = min (1.0f, float (GC之后活着的对象大小) / float (GC之前活着对象大小));
if(cst<((限度的上限-限度的下限)/(限度的下限*(限度的上限 - 1.0f)))
{
限度= ((限度的下限 - 限度的下限* cst)/ (1.0f - (cst * 限度的下限)))
}
else
限度 = 限度的上限 size_t max_growth_size = (限度的上限 / 限度)
if( 当前代的大小 > = max_growth_size)
新分配量= 阈值的上限
else
{
新分配量 = (size_t) min (max ( (限度 * 当前代的大小), gc的最小值), 限度的上限);
限度的上限 = max((新分配量 - 当前代的大小),gc的最小值);
}
}
else //如果是第二代以内的GC
{
cst = GC后活着的对象大小/ GC前活着对象大小
if (cst < ((限度的上限 - 限度的下限) / (限度的下限 * (限度的上限-1.0f))))
限度= ((限度的下限 - 限度的上限*cst) / (1.0f - (cst * 限度的下限)));
else
限度= 限度的上限; 阈值的上限=min (max ((f * (GC后活着对象的大小)), 限度的下限), 限度的上限); }
}

由于这个过程过于复杂,中间省略了一部分计算方式。但是大体都是这样。

以上参考如下:

https://github.com/dotnet/runtime/tree/main/src/coreclr/gc

微信公众号:jianghupt QQ群:676817308

.Net CLR GC 动态加载短暂堆阈值的计算及阈值超量的计算的更多相关文章

  1. Unity动态加载和内存管理(三合一)

    原址:http://game.ceeger.com/forum/read.php?tid=4394#info 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Re ...

  2. 透过现象看本质:Java类动态加载和热替换

    摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...

  3. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)0-------通过应用程序域AppDomain加载和卸载程序集

    本博客中以“C#.Net 如何动态加载与卸载程序集(.dll或者.exe)”开头的都是引用莫问奴归处 微软装配车的大门似乎只为货物装载敞开大门,却将卸载工人拒之门外.车门的钥匙只有一把,若要获得还需要 ...

  4. Unity3D动态加载外部资源

    最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别.Resources ...

  5. Unity3d 动态加载场景物件与缓存池的使用

    聊聊Unity3d动态加载场景物件那些事儿. 众所周知,在策划或美术设计完游戏场景地图后,一个场景中可能会存在成千上万个小的物件,比如石头,木箱子,油桶,栅栏等等等等,这些物件并不是游戏中的道具,仅仅 ...

  6. java中的动态加载和热替换

    https://blog.csdn.net/u010833547/article/details/54312052 ****************************************** ...

  7. unity3d动态加载dll的API以及限制

    Unity3D的坑系列:动态加载dll 一.使用限制 现在参与的项目是做MMO手游,目标平台是Android和iOS,iOS平台不能动态加载dll(什么原因找乔布斯去),可以直接忽略,而在Androi ...

  8. Android动态加载--JVM 类加载机制

    动态加载,本质上是通过JVM类加载机制将插件模块加载到宿主apk中,并通过android的相关运行机制,实现插件apk的运行.因此熟悉JVM类加载的机制非常重要. 类加载机制:虚拟机把描述类的数据从C ...

  9. liteos动态加载(十三)

    1. 概述 1.1 基本概念 动态加载是一种程序加载技术. 静态链接是在链接阶段将程序各模块文件链接成一个完整的可执行文件,运行时作为整体一次性加载进内存.动态加载允许用户将程序各模块编译成独立的文件 ...

随机推荐

  1. web安全之自己写一个扫描器

    web安全之自己写一个扫描器 自己来写一个简单的目录扫描器,了解扫描器的运转机制和原理,因为python写脚本比较容易所以用python写一个网站目录扫描器. 第一步:我们需要导入所需要的库 1 im ...

  2. web安全之信息收集篇

    信息收集 1.网络信息 网络信息就包括网站的厂商.运营商,网站的外网出口.后台.OA. 2.域名信息 通过域名可以查洵网站的所有人.注册商.邮箱等信息 --->Whois 第三方查询,查询子域网 ...

  3. Swift初探03 字符串操作

    字符串操作 01 获取长度 var a = "he l lo" print(a.count) // 计算空格,输出7 02 String.Index类型 String.Index类 ...

  4. SQL多表多字段比对方法

    目录 表-表比较 整体思路 找出不同字段的明细 T1/T2两表ID相同的部分,是否存在不同NAME 两表的交集与差集:判断两表某些字段是否相同 两表的交集与差集:找出T2表独有的id 字段-字段比较 ...

  5. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  6. 一文详解 WebSocket 网络协议

    WebSocket 协议运行在TCP协议之上,与Http协议同属于应用层网络数据传输协议.WebSocket相比于Http协议最大的特点是:允许服务端主动向客户端推送数据(从而解决Http 1.1协议 ...

  7. 详解TCP三次握手(建立TCP连接过程)

    在讲述TCP三次握手,即建立TCP连接的过程之前,需要先介绍一下TCP协议的包结构. 这里只对涉及到三次握手过程的字段做解释 (1) 序号(Sequence number) 我们通过 TCP 协议将数 ...

  8. 医会宝APP登录体验

    帮一个学医生的朋友找相关资料,无意中下载了医会宝APP,登录的时候发现登录方面存在可以优化的地方还挺多,然后随手把登录这部分体验记录下,仅代表个人体验,供新手参考,非权威,交互专家跳过. 一.体验环境 ...

  9. 服务器安装mysql遇到的坑

    服务器安装mysql遇到的坑 一.CentOS7安装MySQL 1.下载:MySQL官方的 Yum Repository wget -i -c http://dev.mysql.com/get/mys ...

  10. 互联网公司目标管理OKR和绩效考核的误区

    最近看了一篇关于「谷歌放弃OKR,转向全新的GRAD系统」的文章,我转到了研发效能DevOps的微信群里,结果引起了大家热烈的讨论,正好我们也在使用 OKR,所以也来谈谈我的理解以及我们应用起来的实际 ...