此页面介绍如何为 Lua 5.1.4 创建紧急垃圾收集器补丁。请注意,LuaFiveTwo 将紧急垃圾收集器列为其包含的功能之一。此补丁的工作与可能包含在 LuaFiveTwo 中的紧急垃圾收集器是分开的。
紧急 GC 补丁使在内存分配失败后安全地调用 Lua 垃圾收集器成为可能。这允许垃圾收集器释放一些内存,以便可以重试失败的分配。该补丁还添加了对设置 Lua 脚本可以分配的内存限制的支持。
文件
[下载 (5.1.4) 版本 6 的紧急 gc 补丁]
[用于对紧急垃圾收集进行压力测试的程序。]
额外的内存优化功能。
这些包含在紧急 GC 补丁中。它们可以在没有紧急 gc 补丁的情况下使用。
- 内部字符串哈希表的调整需要分配额外的哈希表。对于需要以非常小的内存量(64-256kbytes)运行的脚本,当脚本内存不足(仅剩 1-2kbytes)时,这会导致“内存不足”错误。我有一个想法,关于如何在不使用额外哈希表的情况下就地调整哈希表。唯一的缺点是哈希表中的一些字符串将被多次删除和添加。因此,此方法将使用更多 CPU 时间来节省一些额外的内存使用。 [5.1.3 的字符串表补丁]
- Lua 表的哈希部分与字符串哈希表具有相同的调整问题。调整表的哈希部分将需要更多工作,因为调整代码更复杂。 [5.1.3 的哈希部分补丁]
关于 Lua 垃圾收集器工作原理的说明
免责声明:这是我第一次接触垃圾收集器,因此其中一些内容可能不正确。欢迎进行更正/清理。--RobertGabrielJakabosky
"在处理此补丁时,我不得不学习 Lua 中的垃圾收集器是如何工作的。我写下这些内容是为了帮助我以后修复收集器中的更多错误,我希望这些信息可以帮助其他对 Lua 垃圾收集器工作原理感兴趣的人。" --RobertGabrielJakabosky
简单描述
Lua 垃圾收集器是标记和清除收集器。收集器有两个主要阶段:标记和清除,它在每个收集周期运行。在标记阶段,收集器遍历 Lua 堆栈并进入表,将找到的值标记为活动。接下来,清除阶段将遍历所有可收集值的列表,并释放所有找到的死值。
详细描述
所有可收集类型的对象都有一个“标记”位域。这些位定义如下(从头文件“lgc.h”中复制)
- 位 0 - 对象为白色(类型 0)
- 位 1 - 对象为白色(类型 1)
- 位 2 - 对象为黑色
- 位 3 - 对于用户数据:已完成
- 位 3 - 对于表:具有弱键(注意,此位对于用户数据和表具有两个不同的含义)
- 位 4 - 对于表:具有弱值
- 位 5 - 对象已固定(不应被收集)
- 位 6 - 对象为“超级”固定(仅主线程)
垃圾收集器跟踪当前白色(类型 0 或 1),而具有其他白色的对象是死对象,可以在扫描状态期间被收集。
对象的颜色由前 3 位(0、1、2)中设置了哪些位来定义
- 如果两个白色位(0、1)中的一个被设置,而黑色位未被设置,则它是白色。白色对象应仅使用一个白色位。
- 如果所有三个颜色位(0、1、2)都未被设置,则它是灰色。
- 如果黑色位被设置,而两个白色位未被设置,则它是黑色。
垃圾收集器状态(每个收集周期按此顺序经过这些状态)
- GCSpause - 收集周期的开始。在此状态下,所有对象都应使用当前白色标记。主
lua_State
、全局表、注册表和元表被标记为灰色,并添加到灰色列表中。状态现在更改为 GCSpropagate。
- GCSpropagate - 灰色列表中的每个对象都被移除并标记为黑色,然后它引用的任何白色(类型 0 或 1)对象都被标记为灰色,并添加到灰色列表中。一旦灰色列表为空,当前白色就会切换到另一个白色。所有使用旧白色类型标记的对象现在都是死对象。状态现在更改为 GCSsweepstring。
- GCSsweepstring - 检查内部字符串哈希表中每个字符串的颜色。如果颜色与旧白色类型匹配,则该字符串已死,将被释放。如果颜色与当前白色(新创建的字符串)匹配或为灰色(其他一些对象引用它),则它处于活动状态,其颜色将重置为当前白色。一旦所有字符串都被检查,状态就会更改为 GCSsweep。
- GCSsweep - 检查全局 rootgc 列表(此列表保存除字符串之外的所有对象)中每个对象的颜色,就像在 GCSsweepstring 状态期间检查字符串一样。死对象将被释放并从 rootgc 列表中移除。活动对象的颜色将重置为当前白色。一旦所有对象都被检查,状态就会更改为 GCSfinalize。
- GCSfinalize - 此状态将通过运行其
"__gc"
元方法来完成所有死用户数据对象。一旦所有死用户数据对象都被完成,状态就会更改为 GCSpause,这将完成垃圾收集器的一个周期。
--RobertGabrielJakabosky
另请参阅
最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2010 年 12 月 8 日上午 7:05 GMT (差异)