内存管理机制
内存管理自动化内存的分配与回收,防止内存泄漏。它由三部分共享机制组成:垃圾回收(GC)、内存分配器和字符串内部化。
1. 垃圾回收(Garbage Collection, GC)
Lua 的垃圾回收采用增量式标记-清除算法(Incremental Mark-and-Sweep),定期回收不再使用的内存。工作过程分两个阶段:标记阶段从活动对象出发,递归遍历所有被引用的对象并标记为“活动”;清除阶段随后扫描内存,释放所有未被标记的对象占用的内存。为了减少对程序性能的影响,回收不会在单次内完成,而是拆成多个小阶段,分散在程序执行过程中进行。
调优入口是 collectgarbage 函数:可以手动触发回收、调整垃圾回收的参数,也可以调整步进大小和回收阈值来平衡性能与内存占用。
2. 内存分配
内存分配器负责为 Lua 对象分配和释放内存。Lua 在 lua_newstate 时注册一个内存分配函数(lua_Alloc,默认实现基于 realloc),表、字符串、函数原型、协程栈等所有对象的分配与释放都通过这一个入口完成。它不预分配内存池,而是把内存管理交给底层的 C 库(如 glibc 的 malloc),换一个分配器就能接入自定义内存管理。栈与协程栈按需增长、收缩,函数调用所需的槽位在进入时一次性预留,避免了频繁的逐元素扩容。
调优方面,通过 lua_newstate(alloc_func, ud) 传入自己的分配函数,可以实现内存统计、配额限制(例如嵌入式设备上限制 Lua 最多使用多少内存)或对接专用内存池。
3. 内存使用优化
降低内存占用最主要的机制是字符串内部化:Lua 对短字符串做内部化(intern)处理,内容相同的字符串在整个状态中只保存一份,比较时只需比较指针。Lua 核心不为表、函数等对象做池化;如果应用需要(例如游戏开发中的粒子对象),可以用普通表配合弱引用表自己实现对象池。监控内存使用情况、分析垃圾回收的效果,是持续优化的依据。
4. 垃圾回收的挑战和考虑
自动化内存管理也有代价。暂停时间方面,增量式回收虽然压缩了单次停顿,但某些情况下垃圾回收仍可能导致程序暂停,影响实时性要求高的应用。调优难度方面,合理设置回收参数需要对程序的内存使用情况有深入了解,否则可能适得其反。应对办法是定期做性能测试,评估垃圾回收的实际影响,并根据应用场景调整回收策略和参数。
总结
增量式标记-清除负责回收,统一的分配函数加字符串内部化降低分配开销和内存占用,剩下的工作是把参数调到与应用的内存特征匹配。