对于内存的管理,是程序在应用的时候的必需知识点,《Lua设计与实现》中对Lua语言的GC原理做了一个详细的讲解,云风的blog也对其进行了详尽的讲解Lua GC 的源码剖析 系列
给出作者 codedump 在github上的lua源码链接:https://github.com/lichuang/Lua-5.1.4-codedump
这儿就继续做《Lua设计与实现》的阅读笔记,对Lua GC原理及其过程做一个详尽的讲解,由于篇幅较大,就一分为二,写上下篇来讲解整个过程。
 
一、GC的原理及其算法设计
不同的语言,对GC算法的设计不同,常见的GC算法是引用计数和Mark-Sweep算法, c#采用的是Mark-sweep && compact算法, Lua采用的是Mark-sweep算法,分开说一下:
引用计数算法:在一个对象被引用的情况下,将其引用计数加1,反之则减1,如果计数值为0,则在GC的时候回收,这个算法有个问题就是循环引用。
Mark-sweep算法:每次GC的时候,对所有对象进行一次扫描,如果该对象不存在引用,则被回收,反之则保存。
在Lua5.0及其更早的版本中,Lua的GC是一次性不可被打断的过程,使用的Mark算法是双色标记算法(Two color mark),这样系统中对象的非黑即白,要么被引用,要么不被引用,这会带来一个问题:在GC的过程中如果新加入对象,这时候新加入的对象无论怎么设置都会带来问题,如果设置为白色,则如果处于回收阶段,则该对象会在没有遍历其关联对象的情况下被回收;如果标记为黑色,那么没有被扫描就被标记为不可回收,是不正确的。
 
为了降低一次性回收带来的性能问题以及双色算法的问题,在Lua5.1后,Lua都采用分布回收以及三色增量标记清除算法(Tri-color incremental mark and sweep)
 
其基本的原理伪代码,参考书中原文为:
每个新创建的对象颜色设置为白色
//初始化阶段
遍历root节点中引用的对象,从白色置为灰色,并且放入到灰色节点列表中
//标记阶段
while(灰色链表中还有未扫描的元素):
从中取出一个对象,将其置为黑色
遍历这个对象关联的其他所有对象:
if 为白色
标记为灰色,加入到灰色链表中(insert to the head) //回收阶段
遍历所有对象:
if 为白色,
没有被引用的对象,执行回收
else
重新塞入到对象链表中,等待下一轮GC
二、GC的数据结构
分析Lua中对于需要GC的类型数据
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
都会有一个基本的定义CommonHeader,其定义为:
 
next: GCObject链表指针,该指针用来将所有的GC对象都链接在一个表中;
tt: 数据类型:nil, boolean, number, string...
marked: 标记字段,byte表示的字段颜色定义为
这儿特定解释一下为什么会有两种白色,前面提到,5.1后的Lua采用的是三色标记算法,其实质是四色标记算法,分为0型白色和1型白色,在GC回收的时候,会设置当前的白色为其中一种,详见globalstate中的currentwhite,这样在代码回收的时候,如果当前对象的白色不为currentwhite,则认为其不可回收,这样的对象需要等到下一次的GC才能决定是否回收,具体参看后面的,会有对应的应用。对于global_state的设计为:
具体的参数的作用,详见注释,就不在一一解释了
 
三、GC的流程
1、数据的创建
想要了解GC的过程,首先看看数据是怎么在创建的时候被链接到GC链表中的,主要分为三种数据的创建
1) 一般数据的创建 luaC_link
 
简单直接,直接insert to the head
2) upval的创建 luaC_linkupval
3) userdata(udata)的创建 luaS_newdata
 
2、开始GC
整个GC过程分为五个阶段,其定义为
其执行GC的函数为singlestep,来看第一步的操作:
进一步看看markroot的操作:
 
其实就是reset一遍相关的变量,然后标记mainthread, G表,registry表,然后切换到下一个标记阶段。
参看定义:
 
最后都要执行reallymarkobject函数(此处需要展示一下我的竖屏截图便利了:D):
 
基本的注释都解释了各个对象是如何的处理的,udata是不会引用其他类型的数据,所以一步到黑色,upvalue则根据是否为close来决定是否标记到黑色,open状态的upvalue变化较为频繁,需要在后面的remarkupvals中解决。
写到这儿,已经写很长了,为了阅读的便利,让我们下一篇文章继续GC的进程吧:D

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

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

    紧接着上一篇文章zblade:深入探究Lua的GC算法(上)-<Lua设计与实现> 这篇文章让我们收尾GC的具体后续操作.转载请标明出处:http://www.cnblogs.com/zb ...

  2. 浅谈c#和lua的gc

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

  3. lua在MacOS系统上的安装方法

    lua是一种非常小巧的脚本语言,由标准C编写而成,可以很方便的调用c/c++或者被c/c++.另外相关的还有一个luaJIT,是lua在某些平台上的编译器. 我们在这里只安装lua. 1.检测电脑上是 ...

  4. 深入探究jvm之GC的算法及种类

    一.GC基本概念 GC(Garbage Collection)垃圾收集,1960年最早在List中使用.在Java中GC回收的对象是堆空间和永久区,可以有效避免程序员人为造成内存泄漏问题.将堆空间和永 ...

  5. Redis | 第9章 Lua 脚本与排序《Redis设计与实现》

    目录 前言 1. Lua 脚本 1.1 Redis 创建并修改 Lua 环境的步骤 1.2 Lua 环境协作组件 1.3 EVAL 命令的实现 1.4 EVALSHA 命令的实现 1.5 脚本管理命令 ...

  6. 46张PPT讲述JVM体系结构、GC算法和调优

    本PPT从JVM体系结构概述.GC算法.Hotspot内存管理.Hotspot垃圾回收器.调优和监控工具六大方面进行讲述.(内嵌iframe,建议使用电脑浏览) 好东西当然要分享,PPT已上传可供下载 ...

  7. JVM学习(4)——全面总结Java的GC算法和回收机制

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 一些JVM的跟踪参数的设置 Java堆的分配参数 -Xmx 和 –Xms 应该保持一个什么关系,可以让系统的 ...

  8. jvm系列(三):java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...

  9. JVM GC算法 CMS 详解(转)

    前言 CMS,全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性 ...

随机推荐

  1. OneNote中添加代码问题

    OneNote是我最常用的笔记本,然而粘贴代码很麻烦,之前只能屏幕截图如Snipaste自带截图什么的,后来才知道win10自带有win+shift+s自动剪切到草图板上的功能, 然而还是很麻烦. 在 ...

  2. MyBatis3系列__02接口式编程

    hello world MyBatis3支持面向接口编程: 具体做法如下,将helloWorld中的EmployeeMapper.xml文件进行更改: <?xml version="1 ...

  3. 利用Github免费搭建个人主页(转)

    搭建过程涉及: Github注册 Github搭建博客 域名选购 绑定域名 更多 一.  Github注册 在地址栏输入地址:http://github.com/join填写相关信息, 按步骤完成即可 ...

  4. 在deepin上安装YouCompleteMe

    详细安装步骤在github上有,https://github.com/Valloric/YouCompleteMe,我这里是自己总结的简化版安装步骤. 步骤1.安装Vundle 首先,clone到本地 ...

  5. ubuntu 18.04 安装mysql 8.0

    1.下载配置(不然直接装的是mysql5.7): wget https://repo.mysql.com//mysql-apt-config_0.8.10-1_all.deb 2.更新配置: sudo ...

  6. CSS矩形、三角形等

    1.圆形 CSS代码如下:宽高一样,border-radius设为宽高的一半 #circle { width: 100px; height: 100px; background: red; -moz- ...

  7. java代码的编译、执行过程

    Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...

  8. 1.SSM整合_单表的增删改查

    目标:增删改查 环境:Maven+Eclipse+Tomcat7+JDK7 思维导图: 表结构 目录结构 依赖 <dependencies> <dependency> < ...

  9. C++ struct结构体定义构造函数和析构函数,构造函数参数从VS2017平台转换到Qt5平台下构建出错,采用字符集转换函数将string类型转换为wstring,构建仍然出错!

    调试win硬件驱动,需要利用VS编译的win驱动构建自己的Qt5GUI程序: 其中部分win驱动源码如下 device_file::device_file(const std::string& ...

  10. 为wordpress博客网站替换鼠标样式

    第一种方法是使用插件来实现这个功能,Unique Cursor  插件.可以在后台直接安装启用,然后就可以设置喜欢鼠标样式,点击保存就可以了.切记在选择的同时有二个选项一个是disable意思是关闭还 ...