前几篇我们聊了 LuatOS内存分区、GC垃圾回收,基础理论框架已经搭好。但回到真实的开发场景,不少新朋友依然有一连串的疑问:
- zbuff 的大块数据到底占用了哪块内存?
- UART 发送大文件会不会导致内存崩溃?
- MQTT 收发消息时内存如何波动?
- Socket 通信又该如何管理内存……
为了帮助大家更好理解 LuatOS 中 lua、sys、psram 三种内存的实际使用情况,本文将结合合宙 Air780EHM 模组来详细分析。
注意:对于 Air780EHM 来说,sys 分区和 psram 分区都在 PSRAM 上,实际是同一个东西,数据完全一样,所以只看 sys 内存即可。


一、zbuff 功能内存使用分析
zbuff 是 LuatOS 中用于直接操作二进制内存数据的库,内存组成:
- Lua 对象元数据(小,在 Lua 内存);
- C 层数据块(大,如存在 PSRAM 则在 psram 中进行申请,如不存在或失败则在 SRAM 上的 sys 中进行申请)。
1.1 示例代码

1.2 内存分析
通过合宙官方调试工具 Luatools 的内存监控功能,可查看内存数据和曲线图。
新朋友可查看 Luatools 下载和详细使用文档:https://docs.openluat.com/common/Luatools/

1.3 关键结论
1)内存分配特点:
zbuff 通过分离 Lua 元数据(小,存储对象信息)和 C 层数据块(大,存储实际数据),实现了高效的内存管理:
- 大内存块在 sys 分区/psram 分区中分配,不占用 Lua 内存;
- 支持手动释放数据块,避免内存泄漏;
- 创建大内存时自动触发 GC,优化内存使用。
2)使用建议:
处理大块二进制数据(如网络下载、图像解码、文件读写)时,优先使用 zbuff。
二、UART 功能内存使用分析
UART 是嵌入式系统常用通信接口,内存组成:
- lua 配置信息(小);
- sys 发送/接收缓冲区(核心)。
2.1 示例代码

2.2 内存分析

2.3 关键结论
1)内存分配特点:
UART 主要使用 sys 内存作为收发缓冲区,lua 内存仅存储配置对象和回调函数。
发送方式对比:
- 字符串发送:数据需复制到发送缓冲区,有额外内存拷贝;
- zbuff 发送:直接使用 zbuff 数据,无额外内存拷贝,效率更高。
资源管理:
- 发送完成后,发送缓冲区自动释放;
- 调用
zbuff:free() 释放 zbuff 数据块;
- 调用
uart.close() 释放串口相关资源。
2)使用建议:
大数据发送优先使用 zbuff 方式,减少内存拷贝和碎片。
三、MQTT 功能内存使用分析
MQTT 是物联网设备常用的轻量级通信协议,在 LuatOS 中 MQTT 客户端的内存使用涉及 lua 和 sys 内存分配:
- lua 内存: 主要存储客户端对象、配置信息、订阅信息和临时消息对象,占用较小但管理核心逻辑;
- sys 内存: 主要存储连接和收发缓冲区,是内存使用的核心部分,占用较大且随消息大小动态变化。
3.1 示例代码

3.2 内存分析

3.3 关键结论
MQTT 客户端内存使用涉及 lua 和 sys 内存。
1)内存分配特点:
- lua 内存:主要存储客户端对象、配置信息、订阅信息和临时消息对象;
- sys 内存:主要存储连接和收发缓冲区,是内存使用的核心部分。
内存使用特点:
- 创建客户端:lua 内存增长明显(约 38KB);
- 连接服务器:sys 内存增长明显(约 33KB);
- 发布消息:大消息会在 lua 内存中创建临时对象(约 10KB),并在 sys 内存中分配发送缓冲区;
- 多次 GC:通过多次执行
collectgarbage("collect"),内存可几乎完全恢复到初始状态。
2)使用建议:
大消息发布时注意内存使用峰值;不再使用的 MQTT 客户端应及时调用 close() 并设置为 nil;执行多次 GC 操作以确保内存完全回收。
四、Socket 功能内存使用分析
Socket 是网络通信的基础接口,在 LuatOS 中 Socket 的内存使用主要涉及 sys 内存,用于存储发送和接收缓冲区;同时也会使用 lua 内存存储 Socket 对象和配置。
LuatOS 的 socket 库是异步非阻塞 API。
4.1 示例代码

4.2 内存分析

4.3 关键结论
1)内存分配特点
- lua 内存:主要用于存储对象和状态信息,波动较大;
- sys 内存:主要用于实际的缓冲区和内核结构,分配后相对稳定。
2)使用建议:
不再使用的 MQTT 客户端及时调用 socket.release() 释放 socket 资源;使用的 zbuff 缓冲区及时调用 zbuff:free() 释放缓冲区资源;lua 层的内存须进行多次垃圾回收才能完全释放。
通过以上实战分析可以看出,不同功能的内存使用各有特点,但有一个共同原则:
大块数据用 zbuff,异步资源释放要彻底,多次 GC 是关键。 配合 Luatools 的内存监控工具,内存问题便无处遁形。
后续在云栈社区我们继续分享内存泄漏排查与优化实战,敬请关注。
