Ver código fonte

add: 添加用于lua内存分析的profiler库

用于分析lua虚拟机的内存变化,逐一打印malloc/free/realloc行为,记录次数,前后状态
Wendal Chen 3 anos atrás
pai
commit
0c5e9f10e5

+ 33 - 0
components/mempool/profiler/bind/luat_lib_profiler.c

@@ -0,0 +1,33 @@
+#include "luat_base.h"
+#include "luat_malloc.h"
+#include "luat_malloc.h"
+#include "luat_timer.h"
+
+static int l_profiler_start(lua_State *L) {
+    luat_profiler_start();
+    return 0;
+}
+
+static int l_profiler_stop(lua_State *L) {
+    luat_profiler_stop();
+    return 0;
+}
+
+static int l_profiler_print(lua_State *L) {
+    luat_profiler_print();
+    return 0;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_profiler[] =
+{
+    { "start" ,        ROREG_FUNC(l_profiler_start)},
+    { "stop" ,         ROREG_FUNC(l_profiler_stop)},
+    { "print",         ROREG_FUNC(l_profiler_print)},
+	{ NULL,            ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_profiler( lua_State *L ) {
+    luat_newlib2(L, reg_profiler);
+    return 1;
+}

+ 27 - 0
components/mempool/profiler/include/luat_profiler.h

@@ -0,0 +1,27 @@
+#ifndef LUAT_PROFILER_H
+#define LUAT_PROFILER_H
+
+#include "stdint.h"
+
+typedef struct luat_profiler_ctx
+{
+    int tag;
+    int ticks_start;
+    int ticks_stop;
+    uint32_t counter_malloc;
+    uint32_t counter_free;
+    uint32_t counter_realloc;
+    uint32_t lua_heap_begin_used;
+    uint32_t lua_heap_end_used;
+    uint32_t sys_heap_begin_used;
+    uint32_t sys_heap_end_used;
+}luat_profiler_ctx_t;
+
+void* luat_profiler_alloc(void *ud, void *ptr, size_t osize, size_t nsize);
+
+int luat_profiler_start(void);
+int luat_profiler_stop(void);
+
+void luat_profiler_print(void);
+
+#endif

+ 79 - 0
components/mempool/profiler/src/luat_profiler.c

@@ -0,0 +1,79 @@
+#include "luat_base.h"
+#include "luat_malloc.h"
+#include "luat_profiler.h"
+
+#define LUAT_LOG_TAG "profiler"
+#include "luat_log.h"
+
+static luat_profiler_ctx_t ctx;
+
+void* luat_profiler_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
+    // TODO 加调试信息的head, 这样才能记录实际malloc和realloc的大小
+    void* dst = NULL;
+    if (ctx.tag == 0) { // 停用状态, 原样返回
+        return luat_heap_alloc(ud, ptr, osize, nsize);
+    }
+    LLOGD("ud %p ptr %p oszie %08X nsize %08X", ud, ptr, osize, nsize);
+    if (ptr == NULL && nsize == 0) {
+        LLOGD("free NULL");
+        return NULL;
+    }
+    // 如果指针不为NULL, 目标大小为0, 那就是free
+    else if (ptr != NULL && nsize == 0) {
+        LLOGD("call free %p", ptr);
+        ctx.counter_free ++;
+        dst = luat_heap_alloc(ud, ptr, osize, nsize);
+        LLOGD("done free %p", ptr);
+        return dst;
+    }
+    // 如果指针为NULL, 目标大小不为0, 那就是malloc
+    else if (ptr == NULL && nsize > 0) {
+        ctx.counter_malloc ++;
+        LLOGD("call malloc %08X type %08X", nsize, osize);
+        dst = luat_heap_alloc(ud, ptr, osize, nsize);
+        LLOGD("call malloc %08X type %08X %p", nsize, osize, dst);
+        return dst;
+    }
+    // 最后剩下realloc
+    else {
+        ctx.counter_realloc ++;
+        LLOGD("call realloc %08X osize %08X", nsize, osize);
+        dst = luat_heap_alloc(ud, ptr, osize, nsize);
+        LLOGD("call realloc %08X osize %08X %p", nsize, osize, dst);
+        return dst;
+    }
+}
+
+int luat_profiler_start(void) {
+    size_t total; size_t used; size_t max_used;
+    LLOGD("start profiler");
+    memset(&ctx, 0, sizeof(luat_profiler_ctx_t));
+    ctx.tag = 1;
+    luat_meminfo_luavm(&total, &ctx.lua_heap_begin_used, &max_used);
+    LLOGD("%s luavm %ld %ld %ld", "profiler start", total, ctx.lua_heap_begin_used, max_used);
+    luat_meminfo_sys(&total, &ctx.sys_heap_begin_used, &max_used);
+    LLOGD("%s sys   %ld %ld %ld", "profiler start", total, ctx.sys_heap_begin_used, max_used);
+    return 0;
+}
+
+int luat_profiler_stop(void) {
+    size_t total; size_t used; size_t max_used;
+    LLOGD("stop profiler");
+    ctx.tag = 0;
+    luat_meminfo_luavm(&total, &ctx.lua_heap_end_used, &max_used);
+    LLOGD("%s luavm %ld %ld %ld", "profiler stop", total, ctx.lua_heap_end_used, max_used);
+    luat_meminfo_sys(&total, &ctx.sys_heap_end_used, &max_used);
+    LLOGD("%s sys   %ld %ld %ld", "profiler stop", total, ctx.sys_heap_end_used, max_used);
+    return 0;
+}
+
+void luat_profiler_print(void) {
+    size_t total; size_t used; size_t max_used;
+    LLOGD("============================================");
+    // 输出调用次数
+    LLOGD("counter malloc %08X free %08X realloc %08X", ctx.counter_malloc, ctx.counter_free, ctx.counter_realloc);
+    // 输出前后内存大小
+    LLOGD("heap used at start: lua %08X sys %08X", ctx.lua_heap_begin_used, ctx.sys_heap_begin_used);
+    LLOGD("heap used at stop : lua %08X sys %08X", ctx.lua_heap_end_used, ctx.sys_heap_end_used);
+    LLOGD("============================================");
+}

+ 29 - 0
demo/profiler/main.lua

@@ -0,0 +1,29 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "memtest"
+VERSION = "1.0.0"
+
+--[[
+lua内存分析库, 未完成
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+
+sys.taskInit(function()
+    sys.wait(1000)
+    collectgarbage()
+    collectgarbage()
+    sys.wait(1000)
+    profiler.start()
+    while 1 do
+        log.info("sys", rtos.meminfo("sys"))
+        log.info("lua", rtos.meminfo("lua"))
+        sys.wait(3000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 1 - 0
luat/include/luat_libs.h

@@ -141,5 +141,6 @@ LUAMOD_API int luaopen_ftp( lua_State *L );
 LUAMOD_API int luaopen_hmeta( lua_State *L );
 LUAMOD_API int luaopen_sms( lua_State *L );
 LUAMOD_API int luaopen_errdump( lua_State *L );
+LUAMOD_API int luaopen_profiler( lua_State *L );
 
 #endif

+ 8 - 0
luat/modules/luat_main.c

@@ -16,6 +16,10 @@
 #include "luat_errdump.h"
 #endif
 
+#ifdef LUAT_USE_PROFILER
+#include "luat_profiler.h"
+#endif
+
 static int report (lua_State *L, int status);
 
 lua_State *L;
@@ -137,7 +141,11 @@ int luat_main_call(void) {
   // 4. init Lua State
   int status = 0;
   int result = 0;
+#ifdef LUAT_USE_PROFILER
+  L = lua_newstate(luat_profiler_alloc, NULL);
+#else
   L = lua_newstate(luat_heap_alloc, NULL);
+#endif
   if (L == NULL) {
     l_message("lua", "cannot create state: not enough memory\n");
     goto _exit;