本文首先从LuatOS中核心的二进制数据操作库zbuff入手,详细拆解其内存组成结构与分配逻辑——zbuff的内存占用分为两部分,其一为Lua对象元数据,占用空间较小,直接分配在lua内存分区;其二为C层数据块,占用空间较大,其分配逻辑遵循LuatOS的自动内存分配策略,若模组存在PSRAM(如Air780EHM)则优先在psram分区(即Air780EHM的sys分区)申请,若PSRAM不存在或申请失败,则 fallback至SRAM上的sys分区申请,这一特性直接决定了zbuff在大块数据处理场景中的内存使用效率与稳定性。

一、zbuff功能内存使用分析

zbuff是LuatOS中用于直接操作二进制内存数据的库,内存组成:Lua对象元数据(小,在Lua内存);C层数据块(大,如存在PSRAM则在psram中进行申请,如不存在或失败则在SRAM上的sys中进行申请)。

1.1 示例代码

的 sys 中进行申请)。


-- zbuff 内存使用示例_
log.info("初始内存状态:")
log.info("lua:", rtos.meminfo("lua"))
--对于780EHM来说,sys分区和psram分区都在PSRAM上,实际是同一个东西, 数据完全一样,所以只看sys内存即可。
--对于PSRAM以及SRAM都存在的模组,如存在PSRAM则在psram中进行申请,如不存在或失败则在SRAM上的sys中进行申请,
--所以需要根据具体模组来打印sys分区以及psram分区_
log.info("sys:", rtos.meminfo("sys"))
log.info("psram:", rtos.meminfo("psram"))

-- 1. buff_auto这个Lua对象是从lua内存区域分配的,这个对象指向的1MB字节的内存是从sys内存区域分配的
local buff_auto = zbuff.create(1024 * 1024)  -- 申请 1MB 内存
local buff_with_data = zbuff.create(512 * 1024, "initial data")  -- 申请 512KB 带初始数据的 zbuff
log.info("创建 zbuff 后:")
log.info("lua:", rtos.meminfo("lua"))  
log.info("sys:", rtos.meminfo("sys"))  

1.2 内存分析

通过官方调试工具Luatools的内存监控功能,可查看内存数据和曲线图。
image

新朋友可查看Luatools下载和详细使用文档:

1.3 关键结论

1)内存分配特点:**zbuff通过分离Lua元数据(小,存储对象信息)和C层数据块(大,存储实际数据),实现了高效的内存管理:

  • 大内存块在sys分区/psram分区中分配,不占用Lua内存;

  • 支持手动释放数据块,避免内存泄漏;

  • 创建大内存时自动触发GC,优化内存使用。

2)使用建议:**处理大块二进制数据(如网络下载、图像解码、文件读写)时,优先使用zbuff。

二、UART功能内存使用分析

UART是嵌入式系统常用通信接口,内存组成:

  • lua配置信息(小);

  • sys发送/接收缓冲区(核心)。

2.1 示例代码

-- UART 内存使用示例
log.info("初始内存状态:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

local uart_id = 1  -- UART 端口号

-- 1. 初始化 UART
-- 发送和接收缓冲区在 sys 内存中分配

local setup_result = uart.setup(uart_id,  -- 串口 ID
    115200,  -- 波特率
    8,  -- 数据位
    1,  -- 停止位
    uart.NONE,  -- 校验位(uart.NONE/uart.EVEN/uart.ODD)
    uart.LSB,  -- 大小端(uart.LSB/uart.MSB)
    4096  -- 接收缓冲区大小:4KB,发送缓冲区大小固定
)
log.info("初始化 UART 后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 2. 发送数据(字符串方式)
-- 数据首先被复制到 UART 发送缓冲区(sys 内存)
-- 然后由硬件自动发送
local send_data = string.rep("test_data_", 100)  -- 约 900 字节的数据
log.info("发送数据前:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 注册发送完成回调
local function uart_sent_callback(id)
    log.info("UART 发送完成回调:", id)
    -- 发送完成后,发送缓冲区会自动释放
    log.info("发送完成后内存状态:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))
end

-- 注册发送完成事件回调
uart.on(uart_id, "sent", uart_sent_callback)

-- 数据复制到发送缓冲区的操作在 uart.write() 调用中执行
-- 这一步会将 send_data 字符串复制到 UART 发送缓冲区(sys 内存)
uart.write(uart_id, send_data)
log.info("调用 uart.write() 后(数据已复制到发送缓冲区):")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 等待发送完成回调(实际使用中应在回调中处理,这里为演示暂停)
sys.wait(1000)  -- 等待发送完成

-- 3. 发送数据(zbuff 方式)
-- 使用 zbuff 发送数据,减少内存拷贝
local txbuff = zbuff.create(1024)
log.info("创建发送 zbuff 后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 向 zbuff 写入数据
local write_len = txbuff:write("Hello from zbuff!")
log.info("使用 zbuff 发送数据:")

-- 使用 uart.tx() 发送 zbuff 数据
-- 此方式直接使用 zbuff 数据,减少一次内存拷贝
local tx_result = uart.tx(uart_id, txbuff)
log.info("调用 uart.tx() 后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 等待发送完成回调
sys.wait(1000)  -- 等待发送完成

log.info("zbuff 发送完成后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 4. 接收数据回调
-- 接收数据存储在 UART 接收缓冲区(sys 内存)
local rxbuff = zbuff.create(4096)
log.info("创建接收 zbuff 后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

local function uart_receive_callback(id, len)
    log.info("UART 接收数据回调,可用长度:", len)
    -- 从 UART 接收缓冲区读取数据到 zbuff
    local read_len = uart.rx(id, rxbuff)
    if read_len > 0 then
        log.info("实际读取长度:", read_len)
        log.info("接收数据:", rxbuff:toStr(0, read_len))
        -- 接收数据后,UART 接收缓冲区会自动清空
        log.info("接收数据后内存状态:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 重置 zbuff 指针,准备下次接收
        rxbuff:seek(0)
    end
end

-- 注册接收回调
uart.on(uart_id, "receive", uart_receive_callback)

-- 5. 释放资源
-- 释放 zbuff 资源
txbuff:free()
rxbuff:free()
log.info("释放 zbuff 后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 6. 关闭串口
-- 使用 uart.close() 函数关闭串口,释放串口相关资源
uart.close(uart_id)
log.info("关闭串口后:")
log.info("lua:", rtos.meminfo("lua"))
log.info("sys:", rtos.meminfo("sys"))

-- 注意:uart.close() 函数用于关闭串口,释放相关资源
-- 调用后串口将不再可用,需要重新调用 uart.setup() 才能再次使用

2.2 内存分析

通过官方调试工具Luatools的内存监控功能,可查看内存数据和曲线图。

image

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 示例代码

-- MQTT 内存使用示例
log.info("初始内存状态:")
log.info("lua:", rtos.meminfo("lua"))  -- 记录Lua虚拟机内存使用
log.info("sys:", rtos.meminfo("sys"))  -- 记录系统内存使用

-- 配置 MQTT 服务器信息
local SERVER_ADDR = "lbsmqtt.airm2m.com"
local SERVER_PORT = 1884
local USERNAME = "test"
local PASSWORD = "test"
local CLIENT_ID = "luatos_test_device"

-- 定义 MQTT 客户端回调函数
local function mqtt_client_cb(mqtt_client, event, data, payload, metas)
    log.info("MQTT 事件:", event, data, payload and #payload or "nil")

    -- 连接成功事件
    if event == "conack" then
        log.info("MQTT 连接成功")
        -- 连接成功后可以订阅主题
        -- 内存影响:
        --   - lua内存:增加约592B,存储订阅信息
        --   - sys内存:基本不变
        mqtt_client:subscribe("device/commands", 0)
        -- 对应内存分析:步骤 6,订阅主题后
        log.info("订阅主题后内存:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

    end

    -- 接收到消息事件
    if event == "recv" then
        log.info("MQTT 接收消息:", data, #payload, "字节")
        -- 内存影响:接收到消息时的临时内存使用
        -- 对应内存分析:接收消息后,检查消息接收的内存变化
        log.info("接收消息后内存:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 对于大消息,可以使用 zbuff 处理
        -- 内存影响:创建临时zbuff对象,处理完成后释放
        if #payload > 1024 then -- 大于 1KB 的消息
            local buff = zbuff.create(#payload)  -- 创建对应大小的zbuff
            buff:write(payload)  -- 写入数据
            -- 处理数据...
            buff:free()  -- 释放zbuff数据块
        end
    end
end

-- MQTT 客户端需要在 task 中运行
local function mqtt_test_task()
    -- 1. 创建 MQTT 客户端
    -- 参数:nil, 服务器地址, 服务器端口
    -- 内存影响:
    --   - lua内存:增加约38120B,存储客户端对象和内部数据结构
    --   - sys内存:增加约3848B,分配基础结构
    local mqtt_client = mqtt.create(nil, SERVER_ADDR, SERVER_PORT)
    -- 对应内存分析:步骤 3,创建 MQTT 客户端后
    log.info("创建 MQTT 客户端后:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))

    -- 2. 配置认证信息
    -- 内存影响:
    --   - lua内存:增加约264B,存储认证配置
    --   - sys内存:基本不变
    mqtt_client:auth(CLIENT_ID, USERNAME, PASSWORD, true)
    -- 对应内存分析:步骤 4,配置认证信息后
    log.info("配置认证信息后:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))

    -- 3. 注册事件回调
    -- 内存影响:无显著内存变化,仅注册回调函数
    mqtt_client:on(mqtt_client_cb)

    -- 4. 设置 keepalive
    -- 内存影响:无显著内存变化,仅设置参数
    mqtt_client:keepalive(30)

    -- 5. 连接 MQTT 服务器
    -- 内存影响:
    --   - lua内存:增加约160B,存储连接状态
    --   - sys内存:增加约33204B,分配连接和收发缓冲区
    local connect_result = mqtt_client:connect()
    -- 对应内存分析:步骤 5,连接 MQTT 服务器后
    log.info("连接 MQTT 服务器后:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))

    -- 等待连接成功(最多10秒)
    -- 对应内存分析:步骤 2,网络连接就绪,无明显内存变化
    local connected = false
    local start_time = os.time()
    while not connected and os.time() - start_time < 10 do
        sys.wait(1000)
        -- 检查连接状态(实际应用中通过事件判断)
        connected = true -- 简化示例,实际应通过事件回调判断
    end

    if connected then
        -- 6. 发布小消息
        -- 内存影响:
        --   - lua内存:增加约376B,存储消息对象
        --   - sys内存:减少约472B,可能是临时对象释放
        local small_msg = "{\"temp\":25.5,\"humidity\":60}" -- 约 30 字节
        -- 对应内存分析:步骤 7,发布小消息前
        log.info("发布小消息前:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 内存影响:
        --   - lua内存:增加约176B,消息发送相关结构
        --   - sys内存:增加约380B,消息发送缓冲区
        local publish_result = mqtt_client:publish("sensor/data", small_msg, 0)
        -- 对应内存分析:步骤 8,发布小消息后
        log.info("发布小消息后:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 7. 发布大消息
        -- 内存影响:
        --   - lua内存:增加约10328B,存储大消息对象
        --   - sys内存:基本不变
        local large_msg = string.rep("0123456789", 1000) -- 约 10KB 数据
        -- 对应内存分析:步骤 9,发布大消息前
        log.info("发布大消息前:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 内存影响:
        --   - lua内存:增加约208B,消息发送相关结构
        --   - sys内存:增加约12300B,大消息发送缓冲区
        local publish_result = mqtt_client:publish("sensor/large_data", large_msg, 0)
        -- 对应内存分析:步骤 10,发布大消息后
        log.info("发布大消息后:")
        log.info("lua:", rtos.meminfo("lua"))
        log.info("sys:", rtos.meminfo("sys"))

        -- 运行一段时间
        sys.wait(5000)
    end

    -- 8. 断开连接
    -- 内存影响:
    --   - lua内存:增加约376B,断开连接相关操作
    --   - sys内存:减少约12404B,释放连接相关资源
    mqtt_client:disconnect()
    -- 对应内存分析:步骤 11,断开 MQTT 连接后
    log.info("断开 MQTT 连接后:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))

    -- 9. 关闭客户端并释放资源
    -- 内存影响:关闭客户端,准备释放资源
    mqtt_client:close()
    mqtt_client = nil -- 断开引用,等待GC回收

    -- 重复执行多次垃圾回收操作,每次间隔1秒
    -- 目的是彻底释放MQTT客户端占用的资源,确保内存完全回收
    -- 内存影响:
    --   - lua内存:减少约49272B,客户端对象和相关结构完全释放
    --   - sys内存:减少约33436B,释放所有 MQTT 相关资源
    -- 多次执行垃圾回收并间隔等待,确保:
    -- 1. Lua的垃圾回收器采用增量式标记-清除算法,多次调用 collectgarbage("collect") 是为了确保更彻底地回收垃圾
    -- 2. mqtt是异步操作,使用非阻塞函数和事件回调机制来处理网络操作。某些资源的释放可能依赖于异步操作,需要等待系统完成相关处理
    -- 3. 多次回收有助于更有效地整理内存碎片,提高内存使用效率
    for i = 1, 5 do
        collectgarbage("collect")  -- 执行垃圾回收
        sys.wait(1000)             -- 等待1秒,让系统有时间处理垃圾回收
    end

    -- 对应内存分析:步骤 12,关闭客户端并多次 GC 后
    -- 最终状态:
    --   - lua内存:约40248B(接近初始状态的38920B)
    --   - sys内存:约108068B(接近初始状态的104760B)
    log.info("关闭客户端并 GC 后:")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))

    log.info("MQTT 客户端资源已释放")
end

-- 创建并启动 MQTT 测试任务
sys.taskInit(mqtt_test_task)

3.2 内存分析

通过官方调试工具Luatools的内存监控功能,可查看内存数据和曲线图。
image

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 示例代码

-- Socket内存使用情况完整演示

-- 加载libnet库
local libnet = require "libnet"

-- 配置
local SERVER_ADDR = "112.125.89.8"
local SERVER_PORT = 33768
local TASK_NAME = "socket_mem_demo"

-- 内存记录函数
local function log_memory_info(step)
    log.info("=== " .. step .. " ===")
    log.info("lua:", rtos.meminfo("lua"))
    log.info("sys:", rtos.meminfo("sys"))
end

-- 消息回调函数(libnet需要)
local function mem_demo_callback(msg)
    log.info("mem_demo回调")
end

-- 主任务函数
local function socket_memory_task()
    -- 等待网络就绪
    sys.waitUntil("IP_READY", 30000)
    -- 记录初始内存
    -- 对应内存分析:初始状态,记录系统启动后的内存基线
    log_memory_info("初始状态")

    -- 1. 创建socket
    -- 内存影响:
    --   - lua内存:增加约392B,存储socket对象和相关配置信息
    --   - sys内存:增加约108B,分配socket控制块和基础结构
    local socket_client = socket.create(nil, TASK_NAME)
    if not socket_client then
        log.error("创建socket失败")
        sys.cleanMsg(TASK_NAME)
        sys.taskDel(TASK_NAME)
        return
    end
    -- 对应内存分析:创建socket后,检查socket对象分配的内存
    log_memory_info("创建socket后")

    -- 2. 配置socket
    -- 内存影响:配置socket参数,无显著内存变化
    if not socket.config(socket_client) then
        log.error("配置socket失败")
        socket.release(socket_client)
        sys.cleanMsg(TASK_NAME)
        sys.taskDel(TASK_NAME)
        return
    end

    -- 3. 创建接收缓冲区
    -- 内存影响:
    --   - lua内存:增加约248B,存储zbuff对象元数据
    --   - sys内存:增加约1024B,分配1KB的实际接收缓冲区
    local rx_buff = zbuff.create(1024)
    -- 对应内存分析:创建缓冲区后,检查1KB缓冲区的内存分配
    log_memory_info("创建缓冲区后")

    -- 4. 连接服务器
    -- 内存影响:
    --   - lua内存:增加约1032B,存储连接状态、服务器地址信息
    --   - sys内存:减少约284B,内核优化临时缓冲区使用
    log.info("正在连接服务器...")
    local connect_result = libnet.connect(TASK_NAME, 10000, socket_client, SERVER_ADDR, SERVER_PORT)

    if connect_result then
        log.info("连接成功")
        -- 对应内存分析:连接服务器后,检查连接过程的内存变化
        log_memory_info("连接服务器后")

        -- 5. 发送数据
        -- 内存影响:
        --   - lua内存:增加约816B,存储临时发送数据对象和发送状态
        --   - sys内存:减少约80B,发送缓冲区数据被网络层处理后释放
        local test_data = "内存测试数据 " .. os.time()
        local send_result = libnet.tx(TASK_NAME, 5000, socket_client, test_data)

        if send_result then
            log.info("发送成功:", test_data)
            -- 对应内存分析:发送数据后,检查数据发送过程的内存变化
            log_memory_info("发送数据后")
        else
            log.warn("发送失败")
        end

        -- 6. 等待并接收数据
        -- 内存影响:
        --   - lua内存:增加约544B,存储接收到的数据对象和接收状态
        --   - sys内存:增加约148B,内核处理接收到的数据时的临时缓冲区使用
        -- 等待5秒,期间持续检查数据,5秒后无论是否收到数据都继续执行
        local wait_start = os.time()
        local has_received_data = false
        while os.time() - wait_start < 5 do
            -- 检查是否有数据
            local rx_result = socket.rx(socket_client, rx_buff)
            if rx_result then
                if rx_buff:used() > 0 and not has_received_data then
                    log.info("recv data len", rx_buff:used())
                    -- 对应内存分析:接收数据后,检查数据接收过程的内存变化
                    log_memory_info("接收数据后")
                    has_received_data = true
                    -- 收到数据后不立即跳出循环,继续等待剩余时间
                end
            else
                log.error("socket.rx失败")
                -- socket.rx失败也不立即跳出循环,继续等待剩余时间
            end
            sys.wait(200)
        end
        log.info("等待5秒接收数据完成")

        -- 7. 关闭连接
        -- 内存影响:
        --   - lua内存:增加约4768B,连接关闭过程中产生的临时对象和状态信息
        --   - sys内存:增加约188B,TCP四次挥手过程中的状态管理开销
        log.info("正在关闭连接...")
        libnet.close(TASK_NAME, 5000, socket_client)
        -- 对应内存分析:关闭连接后,检查连接关闭过程的内存变化
        log_memory_info("关闭连接后")
    else
        log.error("连接失败")
    end

    -- 8. 释放资源
    -- 内存影响:
    --   - lua内存:增加约168B,资源释放过程中的临时操作
    --   - sys内存:减少约1136B,释放socket控制块和1KB接收缓冲区
    if socket_client then
        socket.release(socket_client)  -- 释放socket控制块
        socket_client = nil  -- 断开引用,等待GC回收
    end

    if rx_buff then
        rx_buff:free()  -- 释放zbuff数据块
        rx_buff = nil  -- 断开引用,等待GC回收
    end

    -- 对应内存分析:释放资源后,检查资源释放的内存变化
    log_memory_info("释放资源后")

    -- 9. 强制垃圾回收
    -- 重复执行多次垃圾回收操作,每次间隔1秒
    -- 目的是彻底释放socket客户端占用的资源,确保内存完全回收
    -- 内存影响:
    --   - lua内存:减少约9344B,回收所有临时对象、socket对象、缓冲区对象等
    --   - sys内存:减少约228B,内核清理剩余的socket相关资源
    -- 多次执行垃圾回收并间隔等待,确保:
    -- 1. Lua的垃圾回收器采用增量式标记-清除算法,多次调用 collectgarbage("collect") 是为了确保更彻底地回收垃圾
    -- 2. socket是异步操作,使用非阻塞函数和事件回调机制来处理网络操作。某些资源的释放可能依赖于异步操作,需要等待系统完成相关处理
    -- 3. 多次回收有助于更有效地整理内存碎片,提高内存使用效率
    for i = 1, 5 do
        collectgarbage("collect")  -- 执行垃圾回收
        sys.wait(1000)             -- 等待1秒,让系统有时间处理垃圾回收
    end

    -- 对应内存分析:垃圾回收后,检查内存恢复情况
    log_memory_info("垃圾回收后")

    -- 10. 内存对比总结
    -- 最终状态:
    --   - lua内存:约42800B(接近初始状态的44176B)
    --   - sys内存:约108052B(接近初始状态的108312B)
    -- 结论:通过完整的资源释放和多次垃圾回收,内存基本恢复到初始状态
    log.info("=== 内存演示完成 ===")

    -- 清理task资源
    sys.cleanMsg(TASK_NAME)
    sys.taskDel(TASK_NAME)
end

-- 使用sys.taskInitEx创建任务(libnet需要)
sys.taskInitEx(socket_memory_task, TASK_NAME, mem_demo_callback)

4.2 内存分析

通过官方调试工具Luatools的内存监控功能,可查看内存数据和曲线图。
image

4.3 关键结论

1)内存分配特点

  • lua内存:主要用于存储对象和状态信息,波动较大;

  • sys内存:主要用于实际的缓冲区和内核结构,分配后相对稳定。

2)使用建议:

不再使用的MQTT客户端及时调用socket.release()释放socket资源;使用的zbuff缓冲区及时调用zbuff:free()释放缓冲区资源;lua层的内存须进行多次垃圾回收才能完全释放。


通过以上实战分析可以看出,不同功能的内存使用各有特点,但有一个共同原则:

大块数据用zbuff,异步资源释放要彻底,多次GC是关键。配合Luatools的内存监控工具,内存问题便无处遁形。

今天就分享到这里了

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐