浅谈你感兴趣的 C# GC 机制底层
本文内容是学习CLR.via C#的21章后个人整理,有不足之处欢迎指导。
昨天是1024,coder的节日,我为自己coder之路定下一句准则--保持学习,保持自信,保持谦逊,保持分享,越走越远。
第一部分—基本原理思想
垃圾回收机制是针对托管堆而言。
不同于C的运行时堆,托管堆是内存是连续的,每次分配新内存,NextObjPtr指针只需要加上新分配内存块大小即可。C运行时堆为了维护链表的完整性,每当分配新的内存时,遍历链表,一旦发现足够大的内存块,则拆分块,修改节点中的指针。从托管堆中分配内存的速度,几乎可以与线程栈分配相媲美。
GC机制回收的就是托管堆中的垃圾对象。
第二部分—基本算法思想
GC检查托管堆中是否有不再使用的对象。
那么什么是不再使用的对象?
首先要解释什么是根(root)。每个应用程序都有一组根,每个根都是一个存储位置,其中包含指向引用类型对象的一个指针。该指针要么运用托管堆中的一个对象,要么为null。类型中定义的任何静态字段被认为是一个根,任何方法参数或者局部变量也被认为是一个根。只有引用类型变量,才被认为是根,值类型的变量永远不被认为是根。
GC开始执行时,假设所有对象都是垃圾。
GC沿着线程栈上检查所有的根,如果发现了一个跟引用堆中的对象,则在这个对象的“同步索引字段”上开启一位,也就是将这个bit设置为1,也就是说这个对象被标记了。
GC就是这样,以递归的方式遍历所有可达的对象。可达的对象也就是说有根的对象,就是在标记阶段被标记的,也就是本次不回收的。所以不可达的对象就被回收了。
进入第二阶段--压缩阶段。
实际上此压缩非彼压缩,在这里是指碎片整理,如何整理呢?如果发现晓得内存块,GC忽略它们,如果发现大的,可用的连续内存块,GC把非垃圾对象移动到这里以压缩堆。
包含只想这些对象的指针的变量和CPU寄存器,现在都会变得无效,NextObjPtr也应重新指向托管堆的结尾。
第三部分—终结列表和F-reachable队列
说到终结列表要从某些不仅占用内存的对象说起,比如FileStream,它不仅占用内存资源,也在占用本地资源。
Finalize方法就是用于释放本地资源的方法。
那么这个终结列表用来做什么呢?微软当然不会画蛇添足,请仔细看好下面这段:
既占用内存资源,又占用本地资源的,在GC回收这样对象所占的内存时,仅仅回收内存时不够的,因为一定要调用Finalize方法来释放本地资源啊!强烈不建议在代码中我们手动Finalize,这需要堆Finalize的实现有相当深刻并且全面的理解。那么微软的GC是什么怎么来给我们执行的呢?这就用到了终结列表,为了一定要保证执行Finalize,在最初我们new操作符分配内存地时候,如果该对象的类型中定义了Finalize方法,那么将该对象的一个指针方法到终结列表当中,当此类对象在托管堆中判定为垃圾的时候,GC扫描终结列表,以查找这些对象的指针,该指针会从终结列表中移除,并追加到F-reachable队列。
那么这个队列干嘛的呢?我认为唯一的目的就是复活对象,并调用Finalize方法释放本地资源(如果对象是死的,我们无法调用其方法),调用方法的是一个微软定义好的优先级比较高的一个线程,听说这样做有很多好处。那么为什么放到F-reachable队列中就复活了?f(finalization)终结,reachable可达的。换言之,可将这个队列看做静态字段那样的一个跟。
第四部分—代的思想和原理
GC机制无论何时,都分为三代,0代,1代,2代。
代是什么,微软关于这个做了假设,新对象生存周期比较短,而老对象倾向于活的久一些。所在代越高的对象,存活的越久,所在代越低的对象,越容易被回收。
代就是托管堆中被分配的内存而已,也可以说把托管堆分成三部分吧?
0代初始的预算大小为256kb,当0代中的内存用完时,为新对象分配内存,0代内存不够用时,GC开始回收第一代,未被标记的对象当然回收,已标记的对象则这些对象提高一代,进入1代区域,与此同理,当一代内存已满时,回收1代,此时根对象也就是标记的对象提升至2代。
再次重点说一下三代预算大小分别为256KB,2MB,10MB,预算大小以提升性能为宜,预算越大,垃圾回收频率越低。再次注意的是,性能提升的理论源于开始的假设:新对象生存期较短,老对象倾向于活的久一些。请仔细看下面一段。
如果GC回收后,0代存活下来的对象很少,或者说回收的内存很多。0代预算可能会从256调整为128。代的分配空间减少,意味着回收频繁回收频繁,但GC所做的工作会减少,从而减小进程的工作集,最理想的状态是0代对象都是当做垃圾被回收,这样不必压缩内存,NextObjPtr指向0代起始处。这样来讲,最开始的假设是是成立的。
浅谈你感兴趣的 C# GC 机制底层的更多相关文章
- 浅谈你感兴趣的 CLR GC 机制底层
本文内容是学习CLR.via C#的21章后个人整理,有不足之处欢迎指导. 昨天是1024,coder的节日,我为自己coder之路定下一句准则--保持学习,保持自信,保持谦逊,保持分享,越走越远. ...
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...
- 浅谈V8引擎中的垃圾回收机制
最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...
- 浅谈JS异步轮询和单线程机制
单线程特点执行异步操作 js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步 ...
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 浅谈 G1 GC 日志格式
在 Java9 中,G1 GC 将成为默认的垃圾收集器,G1 垃圾收集器的关键特性之一是能够在不牺牲吞吐量的同时,限制 GC 暂停时间(即可以设置所需的最大停顿时间). 由于 G1 GC 正在逐渐成为 ...
- ? 这是个很好的问题。Go 当前的 GC 显然做了一些额外的工作,但它也跟其他的工作并行执行,所以在具有备用 CPU 的系统上,Go 正在作出合理的选择。请看 https://golang.org/issue/17969 结束语(Closing notes) 通过研究 Go 垃圾收集器,我能够理解 Go GC 当前结构的背景以及它如何克服它的弱点。Go发展得非常快。如果你对 Go感兴趣,最好继
? 这是个很好的问题.Go 当前的 GC 显然做了一些额外的工作,但它也跟其他的工作并行执行,所以在具有备用 CPU 的系统上,Go 正在作出合理的选择.请看 https://golang.org/i ...
- 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...
随机推荐
- Windows内存小结
以前写过一篇理解程序内存, 当时主要是针对用户态,下面再稍微深入一点: 我们以32位程序为例(不启用AWE), 总共4G虚拟空间,其中低2G属于用户态, 高2G属于操作系统内核, 每个程序都有自己的低 ...
- 翻译-高效DevOps的10项实践
原文链接: http://www.drdobbs.com/architecture-and-design/top-10-practices-for-effective-devops/240149363 ...
- struts2学习笔记之七:Result类型
一:关于Struts2的type类型,也就是Result类型,他们都实现了共同的接口Result,都实现了execute方法 他们体现了策略模式,具体Result类型参见:struts-default ...
- javascript for..in 知识
JavaScript 中for...in...,一直在代码中使用,最初认为,for xx in obj||array 对于arry就xx对应为数组索引,对于obj来说xx对应就是obj中的pr ...
- 【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同 ...
- winform 程序制作自己的数字签名(续)
在上一篇文章<winform 程序制作自己的数字签名>中我们已经可以得到我们程序定制的数字签名了,但是比较讨厌的是每次编译之后,数字签名需要重新手动添加. 我们需要的是在程序编译时自动添加 ...
- Android入门(六)碎片
原文链接:http://www.orlion.ga/493/ 一.碎片 碎片(Fragment)是一种可以嵌入在活动当中的 UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常 ...
- IO流-文本IO\读写二进制数据
文本IO 一.简述 OutputStreamWriter类使用选定的编码方式吧Unicode字符流转换为字节流,InputStreamReader类将包含字节的输入流转为可以产生Unicode字符的读 ...
- codeforces B. Pasha and String(贪心)
题意:给定一个长度为len的字符序列,然后是n个整数,对于每一个整数ai, 将字符序列区间为[ai,len-ai+1]进行反转.求出经过n次反转之后的序列! /* 思路1:将区间为偶数次的直接去掉!对 ...
- Cocos2d-x 3.2 学习笔记(一)环境搭建
目前项目无事,时间比较充裕,因此来学习下cocos2dx,当然本人也是新手一个, 写此笔记做备忘和脚步. 最近3.2版本更新出來了!官方说这是自2.x分支以来修复了超过450个bug,3.2版本是目前 ...