浅谈你感兴趣的 CLR 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代起始处。这样来讲,最开始的假设是是成立的。
浅谈你感兴趣的 CLR GC 机制底层的更多相关文章
- 浅谈你感兴趣的 C# 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 ...
- 浅谈线程池(上):线程池的作用及CLR线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...
- 浅谈 C# CLR 执行模块
前言: 买了这本 CLR via C# 已有些日子了,但是一直没有认真翻过这本书,以前学的知识点都忘光了. 趁着现在下着雨的周末,大体记录一下今天了解的笔记,也好弥补一下 C# 知识上的一些盲点. ...
- 浅谈 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 ...
随机推荐
- zabbix_agentd在windows上安装
zabbix_agentd在Windows环境内客户端的安装与管理 1) 在目标机器上C:\windows目录下新建一个目录,如zabbix_agent: 2) 将zabbix_agent软件 ...
- 在Jenkins上做一个定时闹钟
[本文出自天外归云的博客园] 利用Jenkins定时任务来做一个闹钟,每天隔一段时间提醒自己一下“你该休息了!别老坐着!出去走一走!珍爱生命,远离久坐!” 首先在Jenkins上创建一个node. 创 ...
- 秒杀怎么样才可以防止超卖?基于mysql的事务和锁实现
Reference: http://blog.ruaby.com/?p=256 并发事务处理带来的问题? 相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从 ...
- 基于jQuery的新浪游戏首页幻灯片
分享一款基于jQuery的新浪游戏首页幻灯片,带左右箭头,选项卡缩略图,自动轮播切换的jQuery幻灯片代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: <br>& ...
- OAuth 授权过程工作原理讲解
转自:http://www.imooc.com/article/10931 在一个单位中,可能是存在多个不同的应用,比如学校会有财务的系统会有学生工作的系统,还有图书馆的系统等等,如果每个系统都用独立 ...
- grep和rgrep和fgrep
Linux环境下. (1)grep对标签元字符的表示. [berry@berry:practice] grep 'w\(es\).*\1' text northwest NW Charles Main ...
- 字符串过滤掉所有最邻近的“<”和“>”之间的字符
请编写一个方法,实现如下功能:请输入字符串过滤掉所有最邻近的“<”和“>”之间的字符,将其与字符返回. 例如:输入<html><body>4<5<123 ...
- 正则表达式的使用(C#)
1, C#中与正则表达式相关类. C#中与正则表达式相关类的几个常用类是Regex,Match,Group,Captrue,RegexOption首先我们看看这几个类的类图关系,如何你有正则表达式基础 ...
- 解决mysql开启GTID主从同步出现1236错误问题
解决mysql开启GTID主从同步出现1236错误问题 最近遇到mysql开启gtid做复制时,从库出现1236错误,导致同步无法进行,本文就这问题记录下处理步骤,有关gtid知识在这里不做介 ...
- 实现JTextfield 的右键 复制、剪切、粘贴功能。
http://leagion.iteye.com/blog/572730 ——————————————————————————————————————————————————————————————— ...