1
0
mirror of https://gitee.com/openLuat/LuatOS synced 2025-08-17 22:18:03 +08:00

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

用于分析lua虚拟机的内存变化,逐一打印malloc/free/realloc行为,记录次数,前后状态
This commit is contained in:
Wendal Chen 2022-12-27 23:44:27 +08:00
parent 01dd49fbfa
commit 0c5e9f10e5
6 changed files with 177 additions and 0 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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
demo/profiler/main.lua Normal file
View File

@ -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()之后后面不要加任何语句!!!!!

View File

@ -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

View File

@ -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;