为什么Lua使用垃圾收集器而不是引用计数?

时间:2011-02-15 22:07:31

标签: garbage-collection lua

我自己也听过并经历过:Lua的垃圾收集器会因为脚本部分的增长而导致严重的FPS下降。

我发现这与垃圾收集器有关,例如,每次创建的Vector()userdata对象都会暂时存在,直到收集垃圾为止。

我知道Python使用引用计数,这就是为什么它不需要像Luas GC那样需要的任何巨大的性能执行步骤。

  • 为什么Lua不使用引用计数来摆脱垃圾?

8 个答案:

答案 0 :(得分:15)

因为引用计数垃圾收集器很容易泄漏对象。

琐碎的例子:一个双向链表。每个节点都有一个指向下一个节点的指针 - 它本身由下一个节点指向。如果您只是取消引用列表本身并期望它被收集,那么您只是泄漏了整个列表 - none 节点的引用计数为零,因此它们都会保持相互之间活。使用引用计数垃圾收集器,只要有循环对象,您基本上需要将其视为非托管对象,并在完成后自行处理它。

请注意,除引用计数外,Python还使用适当的垃圾收集器。

答案 1 :(得分:10)

虽然其他人已经解释了为什么需要垃圾收集器,但请记住,您可以将Lua中的垃圾收集周期配置为更小,更少频率或按需。如果您分配了大量内存并且正忙于绘制帧,那么将阈值设置得非常大,以避免收集周期,直到游戏中断为止。

Lua 5.1 Manual on garbage collection

答案 2 :(得分:6)

您根据此声明制作的游戏中使用的是什么版本的Lua?当魔兽世界从Lua 5.0切换到5.1时,垃圾收集造成的所有性能问题都严重减少。

使用Lua 5.0的垃圾收集,收集垃圾(并阻止其他任何事件同时发生)所花费的时间与当前使用的内存量成正比,从而导致大量工作以最小化内存使用魔兽插件。

使用Lua 5.1的垃圾收集,收集器变为增量,因此它不像以前那样收集垃圾时锁定游戏。现在垃圾收集对性能的影响非常小,而大多数用户创建的插件中的代码都是非常低效的代码。

答案 3 :(得分:5)

单独引用计数不足以使垃圾收集器正常工作,因为它不会检测周期。即使Python也不单独使用引用计数。

想象一下,对象A和B各自拥有对彼此的引用。甚至一旦你,程序员不再持有对任何一个对象的引用,引用计数仍然会说对象A和B有引用它们的引用。

有许多不同的垃圾收集方案,有些在某些情况下效果更好,有些在其他情况下效果更好。语言设计者可以尝试选择他们认为最适合他们语言的垃圾收集器。

答案 4 :(得分:3)

通常,引用计数不能完全替代垃圾收集,因为可能存在循环引用。您可能希望阅读this page,了解为什么垃圾收集更适合引用计数。

答案 5 :(得分:2)

您可能也对the Lua Gem about optimization感兴趣,{{3}}也有处理垃圾收集的部分。

答案 6 :(得分:2)

看看一些CPython来源。 C代码的很大一部分是Py_DECREFPy_INCREF。这本令人讨厌,乏味且容易出错的书籍在Lua中消失了。

如果需要,没有什么可以阻止你在C中编写Lua模块来手动管理任何繁重的私有分配。

答案 7 :(得分:1)

这是一个权衡。人们已经解释了某些语言(这与Lua无关)使用收藏家的一些原因,但没有涉及这些弊端。

某些语言,尤其是ObjC,仅使用引用计数。这样做的巨大优势在于释放是确定性的 - 只要你放弃最后一个引用,它就能保证对象立即被释放。当您有内存限制时,这很关键。使用Lua的分配器,如果内存约束需要可预测的释放,则必须添加方法以强制立即释放底层存储,这会导致垃圾收集失败。

“WuHoUnited”说你不能这样做是错误的 - 它在iOS上使用ObjC以及在C ++中使用shared_ptr非常有效。你只需要了解你所处的环境,避免周期或在必要时打破它们。