« 关于地图编辑器的一些想法 | 返回首页 | 关于 manual gc 的代码分析 »

降低 lua gc 的开销

周末有同事问我一个问题,说他们猜测在他们系统里 lua 的垃圾回收过程导致了系统开销过大。而其中有些开销是无谓的。

比如在他们的系统中,有大量的结构化数据是只读的,不会和其它数据产生联系。大多为策划设定的游戏逻辑参数。而偏偏这部分数据结构复杂,在 lua 的 gc 过程中会产生大量的遍历。但我们明明知道,这些数据一定不会被回收掉,且不会影响 gc 的结果。那么有什么方法可以优化呢?

首先,我认为这个问题的提出只是在臆测阶段。这部分结构化数据的存在是否实质性的影响了 gc 的效率尚需分析研究。暂时我没有这个条件,暂且认为有这个优化需求,提出方案如下:

首先,有得必有失。如果想出办法减少 gc 的遍历数据量,必然会增加其它方面的开销。

常规来讲,lua 的 VM 是基于标记-清理的方案 gc ,故而需要保留的数据一定要通过标记。我们只能想办法加快标记过程,而不能回避这一点。

可以考虑使用多个 lua state 。成熟的方案有 lua rings 。我们把大量独立数据(可以是只读也可以是可改写的,关键是要独立)放在一个单独的 lua state 中。这样,对于频繁更新的逻辑 state 里,这些数据是一个整体,即一个 state 对象。标记就只需要做一次了。

代价呢?

代价是,state 间传递数据会有比较大的开销。所以需要精心设计。

或许可以建立一个通用的方案,在母体中创建一份 cache ,不用每次从子 state 中复制数据。而这个 cache 可以是一个 weak table ,发生 gc 时整个扔掉即可。

其实,这个做法就是把 gc 遍历复杂数据结构的代价分摊到单个数据元的读取上了。程序员可以权衡其利弊。当然从结构上说,多个 state 可能能增进结构的稳定性。

btw, 这两年,在完成了 C 下的 gc 模块后,从项目中得到了一些可控 gc 的一些使用经验。如果对系统里参于 gc 的对象在心中有数。最简单的 gc 算法反而可以得到最佳效果(简单指,没有什么分代,没有渐进式的扫描回收)。在我们的系统中,被 gc 管理的对象一直保持在千的数量级,在这个数量级下,一切算法都显得敏捷(n 很小时,复杂度上的影响不大)。

Comments

风哥,我爱你风哥,我爱你风哥,我爱你风哥,我爱你
gc又卡又慢的问题, 用多个lua_state可行么,把只读的丢到其中一个, 只对剩下的进行gc, 你们后来有人这么干过么?
请云风帮我转个意见给有道词典: 我主动取词的时候能不能将我所取词自动计入我的生词本,并记下最后取词时间和该词所取词数。 这样的话我可以按月(或周)系统来记忆经常不认识的单词 谢谢,在有道词典哪里提过意见,没看到任何反馈,麻烦云风了
对于配置文件这类只读变量也可以考虑直接C/C++。
对楼下4位无语了...
风哥俄想你
风哥,我也爱你,哈哈!
好直白的mm
风哥,我爱你

Post a comment

非这个主题相关的留言请到:留言本