这篇文章让我们收尾GC的具体后续操作。转载请标明出处:http://www.cnblogs.com/zblade/
3、GC的扫描阶段 GCSpropagate
只要处于这个阶段,就会分2种情况执行,一个是propagatemark,一个是atomic,让我们分别看其实现过程。
首先看处于灰色链表中一直都有对象的情况,在这步操作当中,是可以分步操作的,整个GC的分步操作,就是在这一步操作中,在每次扫描后,都会返回本次扫描标记的对象的大小之和,再下一个分步执行的时候再继续执行,而一旦进入atomic函数中,就需要一次性的执行,不能再分步执行了。
来看propagatemark函数是如何实现的:
对于table,如果该表是weak表,则退回到灰色状态,否则遍历表的数组和散列表部分进行标记,详见traversetable函数;
对于func,traverseclosure主要对func中的upval进行标记;
对于thread, 则将其移植到grayagain中,放在atomic中进行处理;
对于proto,对其中的字符串、upvalue、局部变量等进行遍历标记;
注意,这儿没有处理string\udata类型数据,这是放在其他部分进行的,不需要进行相关的标记;
 
4、GC 扫描阶段的barrier操作
由于采用分步式增量扫描标记算法,所以会出现在分步操作过程中,新增加的对象与被扫描过的对象之间有引用关系的变化,未来确保黑色对象引用的对象中有白色对象,lua提供了两种操作设计:
1)标记过程向前走一步 luaC_barrierf
如果新建对象是白色,而它被一个黑色对象引用了,那么将这个新建对象颜色从白色变为灰色;
2)标记过程向后走一步 luaC_barrierback
类似于上,此时将引用的它的黑色对象的颜色从黑色变为灰色,使得其重新被扫描一次
(或许你看出截图颜色变了,是的,回家了,又是新的编辑器了~)
从define可以看出,只有table需要进行luaC_barrierback,这是由于table本身设计,就是一个table可能会对应N个key或者value,这样如果新增一个key/value,如果将其置为灰色,然后将其加入gray链表中,这样多个添加会带来较大的性能。
采用向后,就是将该table对象退回到gray状态,这样添加多个,其实质都是只改变该table一次,注意这个gray不是改为gray链中,而是将该table加入到grayagain链中,在扫描完gray链后再扫描grayagain链即可。参考源码即可:
对比向前比较简单了:直接调用reallymarkoject
 
5、GC的atomic操作
当gray链表中对象都标记完成后,会执行一次atomic操作,注意这个操作是不能被打断的,所以叫原子操作,参考源码:
首先处理上一篇文章中提到的对open状态的upvalues,然后处理一次gray链表;
然后处理整个弱表,将lua_State指针指向meta表,然后处理一次gray链表
然后处理grayagain链表,类似于上
然后处理udata,其处理函数为luaC_separateudata:
注释很详细,注意放到tmudata链表中后,是在后续操作再集中处理一次;
处理完基本的几个数据后,atomic会把白色类型切换到下一个GC操作的白色类型,然后修改状态到回收阶段CGSsweepstring, 这儿对sweepstrgc进行了赋初值,是为了下面的字符串定位。
 
6、GC的回收阶段 GCSsweepstring/GCSsweep
首先进入的回收阶段是对字符串的处理
虽然是case,但是其实质是一个循环,每次取出散列表中的一个字符串链表,进行一次遍历回收,sweepwholelist最终会调用到sweeplist,等一下给出源码。
当处理完所有的字符串后,切换到GCSsweep状态:
关键操作是sweeplist,参看其源码:
代码中也对前面说的多色标记中的两种白色的作用做了讲解,otherwhite就是本次不可回收的白色,如果处理的对象的白色就是otherwhite,是不会被回收的
 
7、结束阶段 GCSfinalize
这是整个GC的最后阶段了,来看看其操作的源码:
首先处理,是否有前面提到的tmudata链表, 其操作函数为GCTM:
注意,udata本身有GC方法,未来确保其GC方法的调用,实在这次GC中调用G方法,但是这个udata本身,是在下一次的GC中才会被回收的。udata的GC调用则是在fasttm中调用TM_GC来实现。
初看也会迷糊怎么循环的,其实结合上面的case中的 if(g->tmudata)可以理解,为什么每次GCTM都会执行 g->tmudata的移动赋值操作。
 
最终万事大吉,本次GC流程走完,设置到GCSpause状态,等待下一次GC调用。
 
8、GC的进度控制
其实GC的调用,可以分为两种,一种是自动调用,一个是手动调用
自动调用函数: luaC_checkGC
一般不希望自动GC,可以采用setthreshold,将GCthreshold的值设置为非常大,这样不回自动触发GC
手动调用,则设置GC的相关参数 setthreshold:
estimate是对当前内存使用量的一个预估值,gcpause是一个百分比,通过lua_gc可以设置,另一个gc进度的参数是gcstepmul,其主要影响singlestep函数的调用次数,具体原因参看源码:
整个流程都在注释中讲解了,其中关键是lim的设置,然后不断的调用singlestep, 然后处理GC状态即可,注意setthreshold是设置的两次GC之间的时间间隔。由于修改了threshold,对于关闭自动GC的情况,需要再次重新设置关闭自动GC一次。
 
9、总结
对于lua的GC的原理的探究就到这儿,熟悉一门语言的GC流程后,同理去推导理解其他语言的GC会有很大帮助,同时也可以在平时使用lua的时候,对于GC的一些操作更加知其所以然。大家共勉!
 

深入探究Lua的GC算法(下)-《Lua设计与实现》的更多相关文章

  1. 深入探究Lua的GC算法(上)-《Lua设计与实现》

    对于内存的管理,是程序在应用的时候的必需知识点,<Lua设计与实现>中对Lua语言的GC原理做了一个详细的讲解,云风的blog也对其进行了详尽的讲解Lua GC 的源码剖析 系列 给出作者 ...

  2. 浅谈c#和lua的gc

    前提: 本文参考和借鉴相关博客,相关版权归其所有,我只是做一个归纳整理,所以本文没有任何版权 参考文献和书籍: CLR和.Net对象生存周期:   https://www.cnblogs.com/Wd ...

  3. 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...

  4. 手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    C#下Lua编程支持 xLua为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用. xLua的突破 xLua在功能.性能.易用 ...

  5. Cocos2d-x下Lua调用自定义C++类和函数的最佳实践[转]

    Cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质 ...

  6. 【转】Cocos2d-x下Lua调用自定义C++类和函数的最佳实践

    转自:http://segmentfault.com/blog/hongliang/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明 ...

  7. Win32下 Qt与Lua交互使用(一):配置Qt下Lua运行环境

    偶然间看到Lua这种脚本语言,有点兴趣,简单学习了一下. 发现Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. ...

  8. Win32下 Qt与Lua交互使用:配置Qt下Lua运行环境

    Lua与C++之间可以实现非常强的交互性.Lua中可以使用C++中的函数,C++中也可以使用Lua中的函数.由此可以引发出很多奇思妙想了. 简单来说,Lua动态的特性补充了C++的功能.当然,也看你具 ...

  9. Learning Lua Programming (3) iMac下搭建Lua脚本最好的编码环境(代码补全,编译运行)

    这篇文章参考自http://blog.sina.com.cn/s/blog_991afe570101rdgf.html,十分感谢原作者的伟大创造,本人亲测可行. 这篇文章记录一下如何在MAC系统环境下 ...

随机推荐

  1. poj-1207 THE 3n+1 problem

    Description Problems in Computer Science are often classified as belonging to a certain class of pro ...

  2. CAS 之 Hello World(二)

    CAS 之 Hello World(二) 标签(空格分隔): CAS Intro(介绍) 由上节可知Apereo CAS官方推荐使用 WAR Overlay 的方式进行部署: It is recomm ...

  3. (转)关于 awk 的 pattern(模式)

    本文转自chinaunix http://bbs.chinaunix.net/thread-4246512-1-1.html   作者reyleon 我们知道, awk程序由一系列 pattern 以 ...

  4. Access数据库跨库查询及记录集区分

    医疗设备软件一般都是单机软件,如果是Windows平台,常会选择Access数据库存储结构化数据,因为他轻量,便于部署.然而随着医疗信息化的发展,医生希望对多台单机设备的数据进行管理,采用网络数据库当 ...

  5. C语言程序设计第三次作业--选择结构(1)

    Deadline: 2017-10-29 22:00 一.学习要点 掌握关系运算符和关系表达式 掌握如何判断两个实数相等 掌握常用数学函数的使用 掌握逻辑运算符和逻辑表达式 理解逻辑运算的短路特性 掌 ...

  6. 第14、15週PTA題目的處理

    題目1 選擇法排序 1.實驗代碼 #include <stdio.h> #include <stdlib.h> int main() { int n,index,exchang ...

  7. 安装QT5.02

    1.下载QT5 SDK 下载地址:http://qt-project.org/downloads. 2.安装QT5 下载完后,假设放在Download/,切换到该目录,输入:./qt-linux-op ...

  8. Linux学习--进程创建

    进程创建 在Linux系统下,自己可以创建进程: 当进程执行时,它会被装载进虚拟内存,为程序变量分配空间,并把相关信息添到 task_struct里. 进程内存布局分为四个不同的段: • 文本段,包含 ...

  9. oc中protocol、category和继承的区别

    OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...

  10. PHP截取日期

    date( 'Y-m-d ',strtotime('2017-10-9 12:23:35')) 通过时间格式,获取的是2017-10-9