从CLR GC到CoreCLR GC看.NET Core为云而生

内存分配概要

前段时间在园子里看到有人提到了GC学习的重要性,很赞同他的观点。充分了解GC可以帮助我们更好的认识.NET的设计以及为何在云原生开发中.NET Core会占有更大的优势,这也是一个程序员成长到更高层次所需要经历的过程。在认识GC的过程中,我们先看一下.NET中内存分配的概要知识。
.NET分配内存,主要依据托管资源和非托管资源进行分配。托管资源分配到了托管堆中并受CLR的管理,非托管资源分配到了非托管堆中。该节主要讨论托管资源的分配。
CLR支持两种基本类型:值类型和引用类型。CLR对这两种类型在运行时有两种分配方式:

内存的分配过程如下图所示

需要注意的是,CLR还要维护一个指针,称为NextObjPtr,这个指针指向下一个对象再堆中的分配位置。初始化时,NextObjPtr设为地址空间区域的基地址。一个区域被非垃圾对象填满后,CLR会分配更多的区域,指针也会不断偏移。new操作符会返回对象的引用,就在返回这个引用之前,NextObjPtr指针的值会加上对象占用的字节数来得到一个新值,即下一个对象放入托管堆时的地址。

垃圾回收算法与GC运行机制

常用的垃圾回收算法主要有引用计数算法和引用跟踪算法。引用计算有着明显的缺陷,.NET使用的垃圾回收算法是引用跟踪法。小记:关于垃圾回收算法,我记得有一个知识点,在C#中如果出现了循环引用是否会导致内存溢出?如果比较了解这两种算法就会知道不会溢出。

GC Root

引用跟踪算法,通过一系列GCRoot对象作为起始点,从这些点开始向下搜索,搜索的路径成为引用链,当一个对象到GC没有任何引用链,说明对象可以被回收。

GC Root可以类比树来解释

GC根节点存在于堆栈中,指向Teacher引用对象。它包含一个ArrayList订单集合,由Teacher对象引用。集合本身也包含对其元素的引用,随着搜索深度的增加,树也不断长大。

GC根节点的引用源来自

(1)、堆栈
(2)、全局或静态变量
(3)、CPU寄存器
(4)、互操作引用(COM / API调用中使用的.NET对象)
(5)、对象终结引用(objects finalization references)

GC运行机制

GC引入了代的概念,分为三种代,G0、G1、G2,G0对象生存周期较短,越往后生存周期越长(虽然G2中由于直接存储了大对象,又由于G2不是每次都会扫描,所以大多数情况下,G2中的对象的生存周期比G0中的更长)。

GC运行如下图所示

需要注意的是,CLR想要进行垃圾回收时,会立即挂起执行托管代码中的所有线程,正在执行非托管代码的线程不会挂起。所以再多线程环境下,可能会出现莫名其妙的诡异问题。

下图为GC的整体运行流程,包含五个步骤:


垃圾回收时机与模式

CLR会在一下情况发生时,执行GC操作

      1、当GC的代的预算大小已经达到阈值而无法对新对象分配空间的时候,比如GC的第0代已满;

  2、显式调用System.GC.Collect()(显示调用要慎重,因为手动调用可能会与自动执行的GC冲突,从而导致无法预知的问题);

  3、其他特殊情况,比如,操作系统内存不足、CLR卸载AppDomain、CLR关闭,甚至某些极端情况下系统参数设置改变也可能导致GC回收。

关于GC模式主要有

  • WorkStation GC
  • Server GC
  • Concurrent GC
  • Non-Concurrent GC
  • Background GC

详细信息请参阅:https://www.cnblogs.com/dacc123/p/10980718.html,这篇文章关于GC模式的说明比较详细。

.NET Core 3.0的GC处理

.NET Core 3.0默认更好的支持Docker资源限制,官方团队也在努力让.NET Core成为真正的容器运行时,使其在低内存环境中具有容器感知功能并高效运行。

GC堆限制

.NET Core减少了CoreCLR默认使用的内存,如G0代内存分配预算,以更好地与现代处理器缓存大小和缓存层次结构保持一致。

在新的创建的GC堆数量的策略里,GC保留了一个内存片段,每个堆最小是16M,在低内存限制的机器上也可以很好的运行。在多核CPU的机器上运行时,系统并没有设置CPU的核数限制。例如,如果在48核计算机上设置160 MB内存限制,则不需要创建48个GC堆。也就是说如果设置160 MB限制,则只会创建10个GC堆。如果未设置CPU限制,应用程序可以利用计算机上的所有核心。

有了这样的新策略,可以不需要启用Docker环境下的.NET Core应用的工作站GC的工作负载。

支持Docker内存限制

Docker资源限制建立在cgroup之上,而cgroup是Linux的内核功能。从运行时的角度来看,我们需要定位cgroup原语。

设置cgroup限制时的.NET Core 3.0内存使用规则:

  • 默认GC堆大小:容器上cgroup内存限制的最大值20MB或最大值的75%

  • 每个GC堆的最小保留段大小16MB,这将减少在具有大量内核和小内存限制的计算机上创建的堆数

为了支持容器方案,添加了2个HardLimit配置:

  • GCHeapHardLimit - 指定GC堆的硬限制

  • GCHeapHardLimitPercent - 指定允许此进程使用的物理内存的百分比

如果同时指定了两者,则首先检查GCHeapHardLimit,并且只有在未指定GCHeapHardLimit时才检查GCHeapHardLimitPercent。

如果两者都未指定,但进程正在有内存限制的容器中运行,则默认是使用如下设置:

max(20mb,容器内存限制的75%)

如果指定了hardlimit配置,并且程序在有内存限制的容器中使用,GC堆的使用不会超过hardlimit限制,但总内存仍然受容器的内存限制。所以当我们统计内存消耗时,基于容器内存限制得出的数据。

举例:

进程在设置了200MB限制的容器中运行,用户还将GCHeapHardLimit配置为100MB。

如果把GC限制中100MB限制中的50MB用于GC,而容器限制中剩余的100MB用于其他用途,那么内存消耗即为(50+100)/200=75%。

GC将更积极地执行资源回收与释放,因为GC堆越接近GCHeapHardLimit限制,就越能实现提供更多可用内存的目标,也越能使得应用程序可以继续而又安全地运行。如果算法计算出的结果认为此时的GC效率低下,那么将避免持续执行完全阻塞的GC。

即使GC堆完全压缩,GC依然会抛出一个OutOfMemoryException异常出来,这是因为所分配的堆大小超过了GCHeapHardLimit的限制。

由此可见,.NET Core 3.0的设计是要稳定运行于有资源限制的容器中。

支持DockerCPU限制

在CPU限制的情况下,Docker上设置的值将向上舍入为下一个整数值。此值是CoreCLR使用的最大有效CPU核数。

默认情况下,ASP.NET Core应用程序启用了服务器GC(它不适用于控制台应用程序),因为它可以实现高吞吐量并减少跨核心的争用。当进程仅限于单个处理器时,运行时会自动切换到工作站GC。即使您明确指定使用服务器GC,工作站GC也将始终用于单核环境。

通过计算CPU繁忙时间,设置CPU限制,我们避免了线程池的各种推导性竞争:

  • 尝试分配更多的线程以增加CPU繁忙时间

  • 尝试分配更少的线程,因为添加更多的线程不会提高吞吐量

参考资料:

https://devblogs.microsoft.com/dotnet/using-net-and-docker-together-dockercon-2019-update/

https://github.com/dotnet/designs/blob/master/accepted/support-for-memory-limits.md

https://www.cnblogs.com/dacc123/p/10980718.html

https://blog.csdn.net/koudaidai/article/details/7794793

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307318.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot邮件发送(牛客论坛项目之QQ邮箱发送)

一:邮箱发送原理 1:狂神图解 张三通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器网易分析发现需要去QQ的邮件服务器,通过Smtp协议将邮件转投给QQ的Smtp服务器QQ将接收到的邮件存储在456789qq.com这个邮件账号的空间中李四通过Pop3协…

如果淘宝双十一架构用. Net Core,如何“擒住”高并发、高可用、低延迟?

电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。缓存技术是…

.NET5在开发平台上远优于Java,如何发挥优势?

上周.NET5 RC2已发布,.NET5已经肉眼可见的即将到来,令人期待!从.NET Framework到.NET Core再到.NET5,能看到诸多开发者和公司都在积极拥抱新技术。对比Java,国内主流开发都还停留在Java8,在云原生的互联网时…

leetcode122. 买卖股票的最佳时机 II

一:题目 二:上码 class Solution {/**思路:1.局部最优:我们买入当前股票等哪天遇见最大值的时候买出 赚最大利润2.全局最优:局部最优推出全局最优3.这个利润是可以被分解的 7 1 5 10利润: -6 4 5那么最大利润是459其实就是1买入10卖出,但是我们可以在5这天…

多重继承和菱形问题

翻译自 John Demetriou 2018年4月8日 的文章 《Multiple Inheritance And The Diamond Problem》[1]开篇之前,我假设每个人都知道在面向对象编程中继承是什么,以及它能提供什么好处。我不会深入探究对象继承的基础知识。这篇文章更关注于多重继承和它所面…

Jekins持续集成在ERP研发中的应用实践

源宝导读:“持续集成”是敏捷最佳实践中,保证高质量交付的关键环节之一。本文将介绍明源云ERP系统在研发过程中,应用Jekins平台完成持续集成自动构建的实践。一、认识持续集成持续集成是一种软件开发实践,即团队开发成员经常集成他…

leetcode45. 跳跃游戏 II(java详解)

一:题目 二:上码 class Solution {public int jump(int[] nums) {int ans 0;int curIndex 0;//当前统计出来的可以移动的最远距离的下标int nextIndex 0;//在到达 当前最远距离下标的这段距离内 我们统计出的可以达到的最远距离//如果在统计的过程中 其覆盖范围已经大于数组…

Ids4 认证保护 API 方案更新

壹时刻保持学习的喜悦可能你咋一看这个标题不知道什么意思,其实我也没想好怎么表达,因为是一个特别简单的小知识点。先说下为什么突然说到了Ids4?这几天大家都知道,我在视频《微服务之eShop讲解》,目前讲到了购物车微服…

dotNet Core 3.1 使用 Aspose (部署 Docker)

在之前的文章《dotNET Core中使用Aspose(部署Docker)》中介绍了在 dotNet Core2.1 中使用 Aspose ,并部署到 Docker 中,现在 dotNET Core 升级到了 3.1 ,Docker 镜像发生了变化,一些依赖的安装也有些变化。…

MySQL之一条Update的执行流程

文章目录1:执行的语句2:在更新操作中流程中特有的部分(1):redo log(重做日志)(2):binlog(归档日志)(3):Redo日志跟binlog日志的区别2:执行流程1:执行的语句 update T set c c 1 where ID 2;2:在更新操作中流程中特有的部分 (…

教你打入clr内部: 配置windows上的windbg,linux上的lldb

一:背景1. 讲故事前几天公众号里有位兄弟看了几篇文章之后,也准备用windbg试试看,结果这一配就花了好几天,(づ╥﹏╥)づ,我想也有很多跃跃欲试的朋友在配置的时候肯定会遇到这样和那样的问题,所以我觉得有必…

leetcode周赛6076. 表示一个折线图的最少线段数

气死爹了 用C过不去 换成Java 过了 一:题目 二:上码 class Solution {public int minimumLines(int[][] stockPrices) {Arrays.sort(stockPrices,(o1,o2)->o1[0]-o2[0]);int n stockPrices.length;if (n 1) return 0;int ans 1;for (int i 0; i < n-2; i) {int k1 …

使用代码片段的正确姿势,打造高效的vscode开发环境

全文3928字&#xff0c;阅读时间 10分钟&#xff0c;未来节约时间 15分钟/每天代码片段&#xff08;code snippet&#xff09; 相信大家都或多或少有接触过。在完成一个项目以后&#xff0c;往往都会写出许多有价值的代码&#xff0c;或是绞尽脑汁解决的难题&#xff0c;或是灵…

leetcode周赛6074. 字母在字符串中的百分比

这个简单题也比较狗 上午做的时候一直有个测试点不过 但是题目不给出什么测试点不过 原来是100这个答案 给跪了 一:题目 二:上码 class Solution { public:int percentageLetter(string s, char letter) {if (s.size() 0) return 0;int count 0;for (int i 0; i < s.si…

leetcode周赛6075. 装满石头的背包的最大数量

一:题目 二:上码 class Solution { public:/**思路:求差&#xff0c;将结果放到一个容器当中&#xff0c;然后的话&#xff0c;排序&#xff0c;*/int maximumBags(vector<int>& capacity, vector<int>& rocks, int additionalRocks) {vector<int> …

学完这篇依赖注入,与面试官扯皮就没有问题了。

IOC: Inversion Of Control 控制反转DI: Dependency Injection 依赖注入1.控制反转 Inversion Of Control 的前世今生1.1 IOC理论产生的背景讨论控制反转之前&#xff0c;先看看软件系统提出控制反转的前世今生。一个完整精密的软件系统&#xff0c;组件之间就像齿轮&…

SpringCloud微服之Nacos的学习

1:使用前提 第一步:解压启动Nocos SpringCloudAlibaba 推出了一个名为 Nacos 的注册中心&#xff0c;在国外也有大量的使用。 startup.cmd -m standalone 访问http://localhost:8848/nacos/ 第二步:服务注册 工程目录 在父工程中添加依赖 <dependency><groupI…

前端大佬谈国产开源:VUE 的成功在于社区运营

喜欢就关注我们吧&#xff01;近日&#xff0c;国内首个开源软件基金会 —— 开放原子基金会在深圳国际开源谷举办了 TOC 圆桌论坛。论坛上&#xff0c;基金会 TOC 之一、国内知名前端大佬贺师俊表达了一些有趣的观点&#xff0c;阐述了自己对于国内开源生态的见解。贺师俊认为…

停止精神内耗 每日分享

停止反复犹豫 作家脱不花曾说&#xff1a;“人总是有很多左右为难的事情&#xff0c;如果你在做与不做之间来回纠结&#xff0c;那就停止来回推演&#xff0c;立即去做” 所谓三思而后行 那么如果只停留在三思 那么所有的愿景都将成为遗憾 放弃脑海当中左右不定的想法 扔掉徘…

eShopOnContainers 知多少[12]:Envoy gateways

1. 引言在最新的eShopOnContainers 3.0 中Ocelot 网关被Envoy Proxy 替换。下面就来简要带大家了解下Envoy&#xff0c;并尝试梳理下为什么要使用Envoy替代Ocelot。2. Hello EnvoyENVOY IS AN OPEN SOURCE EDGE AND SERVICE PROXY, DESIGNED FOR CLOUD-NATIVE APPLICATIONS.En…