.NET CLR之垃圾回收(GC)
笔记首发于:lengyueling.cn
什么是CLR
公共语言运行库 (common language runtime,CLR) 是托管代码执行核心中的引擎。
运行库为托管代码提供各种服务,如跨语言集成、代码访问安全性、对象生存期管理、调试和分析支持。
它是整个.NET框架的核心,它为.NET应用程序提供了一个托管的代码执行环境。
它实际上是驻留在内存里的一段代理代码,负责应用程序在整个执行期间的代码管理工作。
它的其中一个重要作用就是进行.NET平台下语言的垃圾回收
GC垃圾回收
什么是垃圾回收
Net程序可以找出某个时间点上哪些已分配的内存空间没有被程序使用,并自动释放它们。
自动找出并释放不再使用的内存空间的机制,就称为垃圾回收机制(Garbage Collection,简称GC)。
.NET CLR使用分代收集算法+标记压缩算法来进行GC。
垃圾回收的对象
对于堆中内存,通过识别它们是否被引用来确定哪些对象是垃圾,哪些对象仍要被使用,垃圾就是没有被任何变量、对象引用的内容。
GC只负责堆内存的垃圾回收,引用类型都是存在堆中的,所以他的分配和释放都需要垃圾回收机制来管理。
栈上的内存是通过系统自动管理的,值类型在栈中分配内存,他们有自己的生命周期,不需要主动对他们进行管理,系统会自动分配和释放。
垃圾回收的主要作用
分配对象(比如说实例化对象的时候负责分配内存给对象)
垃圾回收(比如回收我们写C#代码时产生的垃圾)
分配对象
分为大对象和小对象分配
超过85000字节(83k)的为大对象,否则为小对象
大对象会被存放在第二代内存中,目的是减少性能损耗,提高性能
分配小对象在短暂堆或者由自由对象列表进行分配,分配大对象直接在大对象堆段中
一个区域->多个堆(普通堆和短暂堆)
区域是CLR初始化的时候内存里开辟的一段空间
在CLR中分为3个代:0代(存放短暂堆,存放小对象),1代(存放短暂堆,存放小对象),2代(存放普通堆,同时存放大对象和小对象)
代是GC机制中使用的一种算法(分代算法),每次分配都有可能GC以释放内存(某一代存不下时,或者后面说的各种触发GC的条件成立时)
如果我们有一个堆可以放100个字节,一次GC分配后用了90个字节,剩余的字节就是自由对象,如果有多个堆形成的多个自由对象就是自由对象列表
垃圾回收
触发GC的条件
分配对象找不到可用空间(代空间不足)
分配量超过阈值(CLR初始化时的一个阈值上下限)
收到Windows报告物理内存不足的通知
直接调用GC.Collect()手动触发(unity可以在loading的时候触发)
CLR卸载AppDomain
CLR正在关闭
GC垃圾回收的步骤
1.停止其他线程,切换其他线程到抢占模式
合作模式:在CLR里面运行的线程,可以无限制的访问托管堆和非托管堆
抢占模式:只能访问非托管堆,托管堆不能访问
之所以有这步是因为gc的时候如果不进入抢占模式,可能会造成访问到被回收的对象而发生错误
2.重新判定传入的GC回收目标的代是否合适,主要判断条件有:
碎片空间率
短暂堆剩余空间
卡片扫描效率
物理内存占用率
是否执行后台GC
3.判断是否执行后台GC
执行后台GC,进行标记和清扫
不执行后台GC,则执行普通GC,进行标记、计划、重定位、压缩、清扫等操作
简略版本(标记压缩算法):
如果0代内存满了,gc首先会认为堆中全是垃圾,然后进行下面两步
标记对象:从根(静态对象、方法参数)开始检查被引用的对象,将其标记为可达对象,其他为不可达对象
搬迁对象压缩堆,释放不可达对象,搬迁可达对象到1代,修改引用地址
如果1代内存满了,重复上面步骤,将0代可达对象搬迁到1代,1代可达对象搬迁到2代堆,以此类推。
垃圾回收算法
标记清除(Mark Sweep)
简单描述:
是最基础的GC算法。
分为标记阶段和清除阶段。
标记阶段遍历堆(根的直接引用,然后递归)为所有的活动对象打上标记。
清除阶段(从堆的开始到结束遍历每一个对象)如果是已经标记的,设置为未标记,未标记的连接到空闲链表(用作以后的分配),如果有连续的分块则合并。
如何分配:遍历空闲链表根据策略选择合适的对象,下面是三种策略。
First - fit(遇到大于等于的分块就直接返回)
Best - fit(返回大于等于的最小分块)
Worst - fit(返回最大的分块)
优点:
简单
与保守式GC 算法兼容(也就是不移动对象)
缺点:
碎片化(也就是空闲链表中存在,一堆不连续的小分块,不论采用那种分配策略都无法避免碎片化)
分配速度慢(每次分配都需要遍历空闲链表,举个极端的,每次合适的都是最后一个)
与写时复制技术不兼容(写时复制技术(众多UNIX 操作系统的虚拟存储中用到的高速化方法。)
复制进程的时候大部分内存不会被复制而是共享,共享内存不能直接重写,想要重写得复制到自己的私有空间,不访问共享内存
引用计数(Reference Counting)
简单描述:
每个对象有个计数器,在每次指针更新时,新指向的对象的计数器++
之前指向的对象的计数器--
如果等于0回收,加入空闲链表。
如何分配:遍历空闲链表
优点:
可即可回收垃圾(当计数器为0时直接回收)
最大暂停时间短(每次指针更新时都会回收垃圾)
没有必要沿指针查找(上面的标记清楚算法,需要由根开始查找)
缺点:
计数器值的增减处理繁重
计数器要占用很多位
实现繁琐复杂
循环引用无法回收(比如根引用A ,A和B两个互相引用,当根不引用A的时候 A和B已经是垃圾了,但是互相引用计数器都是1,无法回收)
复制集合(Copy Collection)
简单描述:
把堆平分为From,To两个空间,如果现在活动对象,垃圾是在From空间,从根开始递归(深度遍历),把所有的对象复制到To空间,反之亦然。
如何分配:当前活跃的空间,未分配的部分,按内存顺序分配。
优点:
优秀的吞吐量(能较短时间完成GC,和标记清楚算法比较,标记清楚需要遍历两次,而GC复制遍历一次+复制)
可实现高速分配(直接在未分配的连续空间分配,不需要遍历啥的)
不会发生碎片化(每次执行GC都把活动对象集中在开头,放在堆的一端的行为叫做压缩)
与缓存兼容(深度遍历的复制,有引用关系的对象,在内存中放到了一起)
缺点:
堆使用效率低下(一分为二为两个空间,只有一半的堆能使用)
不兼容保守式GC 算法
递归调用函数(每次进行复制的时候都要调用函数,递归会消耗栈,所以还可能栈溢出)
标记压缩(整理)(Mark Compact)
简单描述:
是CLR使用的GC算法。
结合标记清除算法和复制算法的优点并进行优化
标记阶段遍历堆(根的直接引用,然后递归)为所有的活动对象打上标记
整理阶段将存活对象移向内存的一段,然后清除边界外的对象
优点:
清除了标记-清除算法当中,内存区域碎片化的缺点。
消除了复制算法当中,内存减半的高额代价。
缺点
从效率上来说,标记-整理算法要低于复制算法。
移动对象的同时,如果对象被其它对象引用,则还需要调整引用 的地址。
移动过程中,需要全程暂停用户应用程序,即STW。
分代收集(Generational Collection)
当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。
一般是把堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
而老年代中因为对象存活率高、 没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。
资料参考、拓展阅读
Unity优化之GC分配问题_哔哩哔哩_bilibili(Unity优化之GC分配问题)
.Net CLR视频2021年最新讲解CLR核心机制,CLR模型,性能优化原理。_哔哩哔哩_bilibili(.Net CLR视频2021年最新讲解CLR核心机制,CLR模型,性能优化原理)
第9课:构造、析构、垃圾回收_哔哩哔哩_bilibili(【唐老狮】Unity系列之C#四部曲—C#核心-垃圾回收)
.NET:GC_丿灬鑫崽丶的博客-CSDN博客_.net core 析构函数(.NET:GC)
垃圾回收的算法与实现(一)三类基本算法_璃殇Yiyi的博客-CSDN博客(垃圾回收的算法与实现(一)三类基本算法)
CLR的GC_璃殇Yiyi的博客-CSDN博客(CLR的GC)
unity GC机制简单介绍_ZEKEGU1997的博客-CSDN博客_unity的gc(unity GC机制简单介绍)
Unity优化之GC——合理优化Unity的GC - zblade - 博客园(Unity优化之GC——合理优化Unity的GC)
C#——垃圾回收(GC)_面向大象编程的博客-CSDN博客_c# 垃圾回收(C#——垃圾回收(GC))
lua的GC原理_LJY_rookie的博客-CSDN博客(lua的GC原理)
.NET垃圾回收(GC)原理 - awp110 - 博客园(.NET垃圾回收(GC)原理)
四种垃圾回收算法(标记-清除算法【Mark-Sweep】,复制算法【Coping】,标记-整理算法【Mark-Compact】,分代收集算法【Generational Collection】) - ~晶晶~ - 博客园(四种垃圾回收算法)
标记整理算法(Mark-Compact)_永远的HelloWorld的博客-CSDN博客(标记整理算法(Mark-Compact))
http://t.csdn.cn/BOZ6m(标记-压缩(整理)算法)
浅析CLR的GC(垃圾回收器) - 3WLineCode - 博客园(浅析CLR的GC(垃圾回收器))
公共语言运行库_百度百科(公共语言运行库CLR)
托管代码和非托管代码_qq_38234381的博客-CSDN博客_托管代码和非托管代码(托管代码和非托管代码)
.NET CLR之垃圾回收(GC)相关推荐
- 【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能****
前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC).另外,了解内存管理可以帮助我们理解在每一个程序中 ...
- .net C# 堆 栈 垃圾回收 GC
.NET C# .NET C# .NET C# .NET C# .NET C# .NET C# .NET C# 栈 堆 垃圾回收 GC #1 尽管在.NET framework下我们并不需要担心内存管 ...
- java using idispose_c# 垃圾回收(GC)优化
GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...
- 垃圾回收(GC)浅谈
关于内存 计算机通过两个机制,去实现内存的高效使用. 第一种机制是虚拟内存.硬盘的容量其实是远远大于内存的(RAM),虚拟内存会在内存不足的时候,把不经常访问的内存的数据写到硬盘里.虽然说硬盘容量比较 ...
- python进阶19垃圾回收GC
原创博客链接:python进阶19垃圾回收GC 垃圾收集三大手段 一.引用计数(计数器) Python垃圾回收主要以引用计数为主,分代回收为辅.引用计数法的原理是每个对象维护一个ob_ref,用来记录 ...
- python垃圾回收离职_垃圾回收gc.md
垃圾回收gc python的垃圾收回机制不想c和c++是开发者自己管理维护内存的,python的垃圾回收是系统自己处理的,所以作为普通的开发者,我们不需要关注垃圾回收部分的内容,如果想要深层次理解py ...
- 垃圾回收GC经典算法
目录 垃圾回收GC(Garbage Collection) 1.什么是垃圾 2.为什么要有GC 经典的GC算法 1.基本的一些概念 2.标记清除算法(Mark and Sweep) 3.复制法(cop ...
- IBM JDK(J9)垃圾回收(GC)策略
在IBM JDK 1.5之后,采用了如下的垃圾回收GC策略: 针对吞吐量进行优化 -Xgcpolicy:optthruput(可选) 默认策略.对于吞吐量比短暂的 GC 停顿更重要的应用程序,通常使用 ...
- 第十五章: 菱悦 -垃圾回收GC详解
第 15章 垃圾回收GC详解 文章目录 第 15章 垃圾回收GC详解 1.System.gc() 的理解 1.1.System.gc() 方法 1.2.不可达对象回收行为 2.内存溢出与内存泄漏 2. ...
- C#——垃圾回收(GC)
文章目录 前言 一.垃圾回收是什么 二.好处 三.GC过程 1.GC条件 2.GC步骤 3.Mark-Compact 标记压缩算法 4.Generational 分代算法 5.Finalization ...
最新文章
- 制定 OKR 时,怎样做到「少即是多」?
- 基于引擎的matlab+vc混合编程的配置
- Verilog初级教程(14)Verilog中的赋值语句
- modelsim的库仿真流程--1
- 双目视觉——SGM中的动态规划
- echarts中树图的label的点击_ECharts 堆积木(砖块)游戏
- ubuntu linux下面用wine运行大航海时代4和最新版的QQ
- 巨坑!同事离职前一天,偷偷将一个470欧的色环电阻串进我的电源线中......
- 游戏开发-从零开始 002
- php cdi_本机CDI限定词:@Any和@Default
- mysql索引的使用[下]
- 数据结构和算法:线性表链式存储的简单实现
- Code-NFine:NFine权限控制
- 13.5 Prepared Statements
- Capstone 专注HDMI转VGA DP转VGA DP转HDMI DP转LVDS TYPEC转HDMI拓展方案+设计PCB板图
- SELECT @@IDENTITY 中的@@是什么意思,如何应用?
- Web前端之CSS层叠样式表相关案例
- 移动公网5G配置(一)
- 小白算法学习 凸包 graham
- 将文件大小数值转换成B、KB、MB、GB