这篇文章让我们收尾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. Vue之八 HTML5 History模式

    nginx配置 location / { root /webroot/www/ShopMall3; try_files $uri $uri/ /index.html; } /:访问路径: root:服 ...

  2. PAT-L2-007-gplt真题

    题目分析: 1. 首先,题目说一个家庭有孩子爸爸妈妈等几辈人,可以利用并查集将一个家庭里的所有人变成一个集合: 2. 刚好题目的目的也是这样,输出的是一个家庭人数,人均房产面积,人均房产套数等: 3. ...

  3. IT连创业系列:产品设计之答题模块

    前言: 距上篇写完:IT连创业系列:新的一年,先淫文一篇! 转眼又两个星期了,今天不写文,估计大伙又得等两周了. 所以啊~~ 只能再努力一点了,花一天半天的,继续和大伙分享这让人心碎的创业历程. 这两 ...

  4. js如何获取隐藏的元素的高度

    首先,正常情况下,确保div是有高度的. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  5. Java连接mysql——Establishing SSL connection without server's identity verification is not recommended.

    Establishing SSL connection without server's identity verification is not recommended. 出现这个错误的原因是因为m ...

  6. 20162308 实验一《Java开发环境的熟悉》实验报告

    a 20162308 实验一<Java开发环境的熟悉>实验报告 实验内容 使用JDK编译.运行简单的Java程序. 使用IDEA 编辑.编译.运行.调试Java程序. 实验要求 没有Lin ...

  7. Tornado 用户身份验证框架

    1.安全cookie机制 import tornado.web session_id = 1 class MainHandler(tornado.web.RequestHandler): def ge ...

  8. listview、gradview滚动到最后时,滑动至顶部

    listview.gradview滑动顶端.底部的判断及底部滑动至顶端 mPhotoWall.setOnScrollListener(new AbsListView.OnScrollListener( ...

  9. Flask 扩展 Flask-PyMongo

    安装 pip install Flask-PyMongo 初始化Pymongo实例 from flask import Flask from flask.ext.pymongo import PyMo ...

  10. 第四十八条:如果需要精确的答案,请避免使用float和double

    让一个float或者double精确的表示0.1或者10的任何负数次方值都是不可能.float和double它们执行二进制浮点运算, 它们是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的 ...