为什么Lua使用垃圾收集器而不是引用计数?
我听说并亲身经历过:Lua的垃圾回收器可能会导致游戏的帧数严重下降,因为它们的脚本部分增长。
我发现这与垃圾回收器有关,例如,每个创建的Vector()userdata对象暂时处于未使用状态,直到被垃圾回收。
我知道Python使用引用计数,这就是为什么它不需要像Lua的GC那样执行巨大的性能消耗步骤。
- 为什么Lua不使用引用计数来处理垃圾?
原文链接 https://stackoverflow.com/questions/5010100
参考计数仅仅并不足够作为垃圾回收器正确工作的条件,因为它无法检测到循环引用。即使是 Python 也不仅仅使用参考计数。
假设对象 A 和 B 互相持有引用。即使你作为程序员不再持有任何一个对象的引用,参考计数仍然会提示对象 A 和 B 有指向它们的引用。
有许多不同的垃圾回收方案,某些方案在某些情况下运行得更好,某些方案在其他情况下则运行得更好。由语言设计者负责尝试选择最适合其语言的垃圾回收器。
一般来说,由于可能存在循环引用的情况,引用计数并不是垃圾回收的完全替代品。您可能希望阅读 这个页面,以了解为什么垃圾回收被认为优于引用计数。
虽然其他人已经解释了为什么需要垃圾回收器,但请记住,您可以在 Lua 中配置垃圾收集周期,使其更小、更少或按需进行。如果分配了大量内存并忙于绘制帧,则将阈值设置得非常大,以避免在游戏中断之前进行收集周期。
你所称基于的游戏使用的是哪个版本的 Lua?当《魔兽世界》从 Lua 5.0 转换到 5.1 时,所有垃圾回收引起的性能问题都得到了严重缓解。
在 Lua 5.0 的垃圾回收中,回收垃圾所需的时间(和任何同时运行的内容)与当前使用的内存量成比例,从而导致大量的工作要尽量减少 WoW 插件的内存使用。
在 Lua 5.1 的垃圾回收中,收集器改为渐进式,因此在收集垃圾时不会像以前那样锁定游戏。现在垃圾回收对性能的影响非常小,相比于大多数用户创建的插件中的效率极差的代码而言,垃圾回收仅是较大问题的一部分。
尝试查看一些 CPython 源代码。其中很大一部分的 C 代码是 Py_DECREF
和 Py_INCREF
。在 Lua 中,这种令人讨厌、冗长而易错的记账工作只需要消失即可。
如果需要的话,你可以写 C 的 Lua 模块去手动管理所有的重型私有分配。
它是一种权衡。人们已经解释了一些语言(这与Lua无关)使用收集器的原因,但没有触及到缺点。
一些语言,特别是ObjC,仅使用引用计数。这样做的巨大优势是回收是确定性的-一旦你释放了最后一个引用,就保证对象会被立即释放。当你有内存限制时,这至关重要。使用Lua的分配器,如果内存限制需要预测回收,你必须添加方法来强制底层存储被立即释放,这违背了垃圾回收的初衷。
"WuHoUnited"错误地说你不能这样做——在iOS上使用ObjC和在C++中使用shared_ptr非常有效。你只需要了解你所处的环境,以避免循环或必要时打破循环。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
因为引用计数垃圾收集器容易泄漏对象。
简单的例子:一个双向链表。每个节点都指向下一个节点 - 并且被下一个节点指向。如果您仅取消对列表本身的引用并期望将其收集,那么您刚刚泄漏了整个列表 - 没有节点的引用计数为零,因此它们都将彼此保持活动状态。使用引用计数垃圾收集器,每当您有循环对象时,基本上需要将其视为未受管理的对象,并在完成后显式地处理它。
请注意,Python除了引用计数外还使用了适当的垃圾收集器。