0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

LuatOS 内存核心:Lua GC 垃圾回收深度解析

合宙LuatOS 2026-05-20 08:00 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

嵌入式 IoT 开发中,内存管理是系统长期稳定运行的核心。基于 LuatOS物联网设备,Lua 自动 GC 虽简化了
内存 管理,但理解不当易引发内存泄漏、性能波动等问题。本文结合 LuatOS 实战,解析 Lua GC 核心原理、关键调优参数与开发最佳实践,保障设备内存高效稳定运行。

一、垃圾回收工作原理

Lua采用增量标记-扫描(Incremental Mark-and-Sweep) 算法进行GC垃圾回收,这是一种高效的自动内存管理机制。

该算法的工作过程分为两个主要阶段:

  • 标记阶段(Mark Phase)
    从根对象(全局变量、活跃的局部变量、寄存器等)开始,遍历所有可达对象,将其标记为存活状态。
  • 扫描阶段(Sweep Phase)遍历所有对象,回收未被标记的对象,将其占用的内存标记为可用。

实际应用中,Lua的增量垃圾回收将标记和扫描过程分解为多个小步骤,与程序 执行交替进行。这种设计可以减少垃圾回收对程序响应时间的影响,特别适合实时性要求较高的嵌入式系统

二、垃圾回收示例

下面通过一个具体的Lua脚本示例来了解垃圾回收的过程:

![-- Lua 垃圾回收示例 log.info("初始内存使用:", collectgarbage("count"), "KB") -- 创建一些对象 local function create_objects() -- 创建根对象:全局变量(可达) _G.global_table = {} -- 创建局部变量:活跃的局部变量(可达) local local_table = {} -- 创建嵌套对象 _G.global_table.nested = {} local_table.nested = {} -- 创建循环引用对象(可达) local cycle1 = {} local cycle2 = {} cycle1.ref = cycle2 cycle2.ref = cycle1 -- 创建不可达对象链 local unreachable = {} unreachable.next = {} unreachable.next.next = {} log.info("创建对象后内存使用:", collectgarbage("count"), "KB") -- 返回局部变量,使其成为根对象 return local_table, cycle1 end -- 执行对象创建 local active_table, active_cycle = create_objects() -- 现在: - _G.global_table :全局变量,直接被_G引用,是根对象,处于存活状态。 -- local_table (返回后为active_table):局部变量,通过返回值被外部引用,是根对象,处于存活状态。 -- _G.global_table.nested :嵌套对象,被_G.global_table引用,可达,处于存活状态。 -- local_table.nested (返回后为active_table.nested):嵌套对象,被local_table引用,可达,处于存活状态。 -- cycle1 (返回后为active_cycle):局部变量,通过返回值被外部引用,与cycle2循环引用,是根对象,处于存活状态。 -- cycle2 :局部变量,与cycle1循环引用,通过active_cycle可达,处于存活状态。 -- unreachable :局部变量,函数返回后无外部引用,不可达,成为垃圾。 -- unreachable.next :嵌套对象,被unreachable引用,不可达,成为垃圾。 -- unreachable.next.next :嵌套对象,被unreachable.next引用,不可达,成为垃圾。 log.info("执行后内存使用:", collectgarbage("count"), "KB") -- 手动触发垃圾回收 collectgarbage("collect") log.info("垃圾回收后内存使用:", collectgarbage("count"), "KB")](https://pic-private.zhihu.com/v2-670275b4cf7f82b2d81cd5a79699fa69~resize:1440:q75.png?source=1f5c5e47&expiration=1779166915&auth_key=1779166915-0-0-a757fbb7b8640fbc71c366ec71d1dd89&protocol=v2&sampling=False&animatedImagePlayCount=1&overTime=60&incremental=False&sceneCode=article_draft_web&animatedImageAutoPlay=False&retryCount=3&precoder=False)

wKgZO2oL6rCADyFXAAaKrBp0VtI213.pngwKgZPGoL6rWAYH_SAAKU3VgjT1Q218.png

运行结果分析

  • 创建对象后,内存显著增加。
  • 函数返回后,unreachable及其链表失去引用,成为“垃圾”但尚未回收。
  • 手动GC后,内存下降,不可达对象被清理。

**关键点说明:**循环引用不影响GC——cycle1和cycle2互相引用,但因为它们仍被外部active_cycle引用,所以是可达的,不会被回收。只有当整个循环引用链失去外部引用时,才会被正确回收。

三、控制GC行为的两个关键参数

Lua垃圾回收器的行为由两个关键参数控

3.1 间歇率(Pause)

控制垃圾回收器开始新一轮回收的阈值。默认值为200,表示当内存使用量达到上次回收时的两倍时,开始新的回收循环。

  • 值越小,垃圾回收越频繁,内存占用越低,但CPU开销越大;
  • 值越大,垃圾回收间隔越长,内存占用越高,但CPU开销越小。

3.2 步进倍率(Step Multiplier)

控制垃圾回收器的工作速度相对于内存分配速度的倍率。默认值为200,表示垃圾回收器以内存分配速度的两倍工作。

  • 值小于100时,垃圾回收速度慢于内存分配速度,可能导致内存无限增长;
  • 值越大,垃圾回收越积极,每次回收的内存越多。

四、collectgarbage() 核心用法

Lua提供了collectgarbage([opt[, arg]]) 函数用于控制自动内存管理,该函数在LuatOS中同样可用。

4.1 函数主要用法

wKgZPGoL6ryAVk2EAAQNI2FcWZc321.png

4.2 重点参数使用示例

通过合理使用 “count”、“collect” 和 “setpause” 这三个核心参数,你可以有效监控和控制Lua虚拟机的内存使用,优化应用程序的性能和稳定性。

下面通过一个详细的示例,结合日志输出重点讲解:

-- Lua 垃圾回收示例 log.info("初始内存使用:", collectgarbage("count"), "KB") -- 创建一些对象 local function create_objects() -- 创建根对象:全局变量(可达) _G.global_table = {} -- 创建局部变量:活跃的局部变量(可达) local local_table = {} -- 创建嵌套对象 _G.global_table.nested = {} local_table.nested = {} -- 创建循环引用对象(可达) local cycle1 = {} local cycle2 = {} cycle1.ref = cycle2 cycle2.ref = cycle1 -- 创建不可达对象链 local unreachable = {} unreachable.next = {} unreachable.next.next = {} log.info("创建对象后内存使用:", collectgarbage("count"), "KB") -- 返回局部变量,使其成为根对象 return local_table, cycle1 end -- 执行对象创建 local active_table, active_cycle = create_objects() -- 现在: - _G.global_table :全局变量,直接被_G引用,是根对象,处于存活状态。 -- local_table (返回后为active_table):局部变量,通过返回值被外部引用,是根对象,处于存活状态。 -- _G.global_table.nested :嵌套对象,被_G.global_table引用,可达,处于存活状态。 -- local_table.nested (返回后为active_table.nested):嵌套对象,被local_table引用,可达,处于存活状态。 -- cycle1 (返回后为active_cycle):局部变量,通过返回值被外部引用,与cycle2循环引用,是根对象,处于存活状态。 -- cycle2 :局部变量,与cycle1循环引用,通过active_cycle可达,处于存活状态。 -- unreachable :局部变量,函数返回后无外部引用,不可达,成为垃圾。 -- unreachable.next :嵌套对象,被unreachable引用,不可达,成为垃圾。 -- unreachable.next.next :嵌套对象,被unreachable.next引用,不可达,成为垃圾。 log.info("执行后内存使用:", collectgarbage("count"), "KB") -- 手动触发垃圾回收 collectgarbage("collect") log.info("垃圾回收后内存使用:", collectgarbage("count"), "KB")

1)“count” 参数

**功能说明:**返回Lua虚拟机当前使用的总内存,单位为KB(带小数精度)。

使用场景:

  • 监控内存使用趋势;
  • 调试内存泄漏问题;
  • 评估垃圾回收效果。

日志解析:

=== 1. 初始内存状态 ===

初始内存: 120.50 KB

=== 2. 创建大量对象 ===

创建 5000 个对象后内存: 356.75 KB

内存增加: 236.25 KB

关键说明:

返回值包含小数部分,提供精确的内存使用情况;包括Lua VM管理的所有内存,包括已分配但未使用的内存;是监控内存变化的主要工具。

2)“collect” 参数

**功能说明:**执行一次完整的垃圾回收循环,包括标记、扫描和清理阶段。

使用场景:

  • 手动触发垃圾回收,释放不再使用的内存;
  • 在内存敏感操作前清理内存;
  • 测试和调试垃圾回收行为。

日志解析:

=== 4. 使用 collect 参数触发垃圾回收 ===手动 GC 前内存: 356.75 KB手动 GC 后内存: 220.30 KBGC 释放内存: 136.45 KB

关键说明:

执行完整的垃圾回收流程,释放所有不可达对象;阻塞执行,直到垃圾回收完成;适用于需要立即释放内存的场景。

3)“setpause” 参数

**功能说明:**设置垃圾回收器的间歇率,控制垃圾回收开始的阈值。

工作原理

  • 间歇率默认值为200,表示当总内存使用量达到上次GC后活跃内存的2倍时,触发新一轮GC;
  • 公式:触发条件=当前内存>(基准内存×pause/100);
  • 基准内存:每次GC完成后更新的活跃内存量;
  • pause值:百分比单位,100 表示 100%。

使用场景:

  • 调整垃圾回收频率,平衡内存使用和CPU开销;
  • 针对不同应用场景优化垃圾回收行为;
  • 在内存紧张时降低间歇率,提高回收频率。

关键说明:

  • 间歇率越低,垃圾回收越频繁,内存占用越低,但CPU开销越大;
  • 间歇率越高,垃圾回收间隔越长,内存占用越高,但CPU开销越小;
  • 不同应用场景需要不同的设置:
    内存敏感应用:设置较低的间歇率(如100-150);
    CPU敏感应用:设置较高的间歇率(如300-500);
    平衡需求:使用默认值200。

五、最佳实践应用

在实际开发中,合理运用GC相关参数和监控手段,能有效提升程序的内存稳定性和运行效率。

5.1 内存监控

定时打印内存日志,观察内存变化。

sys.timerLoopStart(function() log.info("mem.lua", rtos.meminfo()) log.info("mem.sys", rtos.meminfo("sys")) --log.info("mem.psram", rtos.meminfo("psram")) --需要时打开 end, 3000)

5.2 手动GC时机

在内存敏感操作前(如加载大图片、接收大文件)手动执行GC,确保内存充足。

sys.timerLoopStart(function() log.info("mem.lua", rtos.meminfo()) log.info("mem.sys", rtos.meminfo("sys")) --log.info("mem.psram", rtos.meminfo("psram")) --需要时打开 end, 3000)

5.3 间歇率优化

根据应用场景调整间歇率,平衡内存与性能。

-- 根据应用场景调整间歇率 collectgarbage("setpause", 150) -- 更频繁的 GC --collectgarbage("setpause", 300) -- 较少的 GC,节省 CPU

理解增量标记-扫描的原理,掌握collectgarbage的用法,你就能在内存占用和CPU开销之间找到最佳平衡点。配合前两期的内存分区知识,你已经具备了LuatOS内存管理能力。

LuatOS提供非常快速的通信+外设驱动+
UI 交互+视觉的低功耗实现,相比串口屏+DTU,相比安卓,功耗减半。成本不到三分之一。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5212

    文章

    20756

    浏览量

    338497
  • 内存
    +关注

    关注

    9

    文章

    3255

    浏览量

    76570
  • LuatOS
    +关注

    关注

    0

    文章

    179

    浏览量

    2760
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    深入剖析高性能内存回收技术

    众所周知,内存是操作系统的一项重要资源,直接影响系统性能。而在应用蓬勃发展的今天,系统中运行的应用越来越多,这让内存资源变得越来越紧张。在此背景下,方舟JS运行时在内存回收方面发力,推
    发表于 07-20 09:34 1308次阅读

    C++与lua联合编程

    内存空间和垃圾回收GC)机制。如果让两者直接互相读写内存,不仅会引发极其昂贵的“指针越界”等灾难性后果,还会导致双方
    发表于 04-19 16:27

    LuatOS是什么?

    硬件的实时操作系统,深度整合Lua语言,只需少量内存和Flash空间就能运行,用户编写Lua代码即可实现各种
    发表于 11-08 06:27

    【合宙Air820开发板免费试用】通过LCD学习LuatOSLua,硬件篇

    ,知道了LuatOSLua之间的关系,LuatOS就像是一个可以运行Lua的环境,与之前开发过microPython一样的,都是轻量的脚本开发,但
    发表于 12-28 00:06

    解密方舟的高性能内存回收技术——HPP GC

    (全称Garbage Collection),字面意思是垃圾回收。在计算机领域,GC就是找到内存中的垃圾,释放和
    发表于 07-20 10:44

    Java垃圾回收新算法

    Java与以往的高级语言如C/C++相比,在开发方面具有很大的优势,其中以对象内存管理机制中的垃圾处理机制(GC)最为突出。
    发表于 05-11 10:53 1590次阅读
    Java<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>新算法

    固态硬盘垃圾回收方法

    。特别是对于频繁使用的有数据碎片的SSD,垃圾回收带来的性能下降问题将更为严重,现有的垃圾回收GC)算法各自侧重
    发表于 12-03 10:50 2次下载
    固态硬盘<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>方法

    基于逻辑区间热度的垃圾回收算法

    针对现有的NAND闪存垃圾回收算法中回收性能不高,磨损均衡效果差,并且算法内存开销大的问题,提出了一种基于逻辑区间热度的垃圾
    发表于 12-05 18:27 0次下载
    基于逻辑区间热度的<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>算法

    Jvm垃圾回收机制及性能调优实战

    JVM中自动检测并移除不再使用的数据对象的这种机制称为:垃圾回收,简称GC。JVM通过使用垃圾收集器及使用相应的垃圾
    发表于 04-03 14:31 2次下载

    带颜色的JVM垃圾回收三色标记法

    三色标记法是一种垃圾回收法,它可以让JVM不发生或仅短时间发生STW(Stop The World),从而达到清除JVM内存垃圾的目的。JVM中的CMS、G1
    的头像 发表于 10-20 14:23 2549次阅读

    Kubernetes容器垃圾回收的策略

    Kubernetes的垃圾回收由kubelet进行管理,每分钟会查询清理一次容器,每五分钟查询清理一次镜像。在kubelet刚启动时并不会立即进行GC,即第一次进行容器回收为kubel
    的头像 发表于 08-15 09:16 2392次阅读

    JVM入门之垃圾回收算法

    根据如何判定对象是垃圾垃圾回收算法分为两类:1、 「引用计数式垃圾收集」 (判定垃圾是通过引用计数器)别名:直接
    的头像 发表于 02-10 11:40 1537次阅读
    JVM入门之<b class='flag-5'>垃圾</b><b class='flag-5'>回收</b>算法

    详细解析JVM中的垃圾回收机制

    Java语言的一大优势在于其具有自动垃圾回收(Garbage Collection,GC)机制,让开发者无需关心内存的分配与释放。
    的头像 发表于 06-06 16:53 2985次阅读

    LuatOS框架的使用(上)

    在资源受限的物联网终端设备中,如何实现快速开发与稳定运行是关键挑战。LuatOS框架通过将Lua语言与底层硬件抽象层深度融合,提供了一套简洁高效的开发范式。本文将围绕LuatOS框架的
    的头像 发表于 01-27 19:38 463次阅读
    <b class='flag-5'>LuatOS</b>框架的使用(上)

    LuatOS内存分配机制

    不同 LuatOS 硬件平台在内存布局上存在差异,Lua 运行内存、系统内存与 PSRAM 扩展内存
    的头像 发表于 04-16 12:37 208次阅读
    <b class='flag-5'>LuatOS</b>的<b class='flag-5'>内存</b>分配机制