• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

解析Lua中的GC

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Lua回收算法的原理:

不同的语言,对GC算法的设计不同,常见的GC算法是引用计数和Mark-Sweep算法, c#采用的是Mark-sweep && compact算法

Lua采用的是Mark-sweep算法,分开说一下:

引用计数算法:在一个对象被引用的情况下,将其引用计数加1,反之则减1,如果计数值为0,则在GC的时候回收,这个算法有个

问题就是循环引用。

Mark-sweep算法(标记清除法):

标记:每次执行GC时,先以若干根节点开始,逐个把直接或间接和它们相关的节点都做上标记;

清除:当标记完成后,遍历整个对象链表,把被标记为需要删除的节点一一删除即可。

Lua垃圾回收有三种颜色:

白色:可回收状态。(分为白1,白2)

      如果该对象未被GC标记过则此时白色代表当前对象为待访问状态。举例:新创建的对象的初始状态就应该被设定为白色,因

为该对象还没有被GC标记到,所以保持初始状态颜色不变,仍然为白色。如果该对象在GC标记阶段结束后,仍然为白色则此时

白色代表当前对象为可回收状态。但其实本质上白色的设定就是为了标识可回收。

灰色:中间状态。

      当前对象为待标记状态。举例:当前对象已经被GC访问过,但是该对象引用的其他对象还没有被标记。

黑色:不可回收状态。

      当前对象为已标记状态。举例:当前对象已经被GC访问过,并且对象引用的其他对象也被标记了。

着色图:

 

Lua回收的四个阶段:

#define GCSpause 0 每个 GC 流程的启始步骤。只是标记系统的根节点。
#define GCSpropagate 1
#define GCSsweepstring 2
#define GCSsweep 3
#define GCSfinalize 4

(1)标记阶段:把根节点的集合(由lua语言可以直接访问的对象组成)标记为活跃状态,在lua语言中,这个集合值包括注册表,

保存在一个活跃对象中的对象是程序可达的,因此也会被标记为活跃(弱引用表中的内容除外)当所有可达对象都被标记为活跃后

标记阶段结束。

(2)清理阶段:首先,lua语言会遍历所有的被标记为需要进行析构,但是又没有被标记为活跃状态的对象。这些没有被标记为

活跃状态的对象会被标记为活跃(复苏),并且被放在一个单独的列表中,这个列表会在析构阶段用到,然后,lua语言遍历弱引用表

并从中移除键或值未被标记的元素。

(3)清除阶段:遍历所有的对象(lua会把所有创建的对象放在一个链表中),如果一个对象没有被标记为活跃状态,就将其回收,

否则,就清理标记,然后准备进入下一个清理周期。

(4)析构阶段:调用清理阶段被分离出来的对象的析构器(我的理解就是拿到清理阶段的列表,清理列表中的对象,列表只包含

真正需要清理的对象,那些在弱引用表中被标记的元素已经从列表中移除,也就是有__gc 方法的对象)。

图解:

 

GC的api:

(自动调用GC:当lua使用的内存到达阀值)

(该api为手动调用GC)

opt参数可以为:

  • “collect”:执行一个完整的垃圾回收周期,这是一个默认的选项
  • “stop”:停止垃圾收集器(如果它在运行),实现方式其实就是将gc.threshold设置为一个巨大的值,不再触发gc step操作
  • “restart”:将重新启动垃圾收集器(如果它已经停止)。
  • “count”:返回当前使用的的程序内存量(单位是Kbytes),返回gc->total/1024
  • “step”:执行垃圾回收的步骤,这个步骤的大小由参数arg(较大的数值意味着较多的步骤),如果这一步完成了一个回收周期则函数返回true。
  • “setpause”:设置回收器的暂停参数,并返回原来的暂停数值。该值是一个百分比,影响gc.threshold的大小,即影响触发下一次gc的时间,设置代码如下:

    g->gc.threshold = (g->gc.estimate/100) * g->gc.pause;

    g->gc.estimate为当前实际使用的内存的大小,如果gc.pause为200,则该段代码表示,设置gc的阈值为当前实际使用内存的2倍

  • “setstepmul”:设置回收器的步进乘数,并返回原值。该值代表每次自动step的步长倍率,影响每次gc step的速率,具体这么影响可以查看后面小节

参考:https://blog.csdn.net/BigBrick/article/details/85317491

            https://blog.csdn.net/SamGeren/article/details/108066380

 

 

 

 

 

 

 

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua源代码阅读(五)数据栈与调用栈组成的 线程(协程)发布时间:2022-07-22
下一篇:
如何利用VS编译lua源码发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap