Commit c839efc3 authored by nanahira's avatar nanahira

add memory tracer

parent ca5bd0f5
#include "LuaMemTracker.h"
LuaMemTracker::LuaMemTracker(lua_Alloc alloc_func, void* ud, size_t mem_limit)
: real_alloc(alloc_func), real_ud(ud), limit(mem_limit) {
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
time_t now = time(nullptr);
char filename[64];
std::snprintf(filename, sizeof(filename), "memtrace-%ld.log", static_cast<long>(now));
log_file = std::fopen(filename, "a");
if (log_file) {
std::fprintf(log_file, "---- Lua memory tracking started ----\n");
}
#endif
}
LuaMemTracker::~LuaMemTracker() {
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
if (log_file) {
std::fprintf(log_file, "---- Lua memory tracking ended ----\n");
std::fclose(log_file);
log_file = nullptr;
}
#endif
}
void* LuaMemTracker::AllocThunk(void* ud, void* ptr, size_t osize, size_t nsize) {
return static_cast<LuaMemTracker*>(ud)->Alloc(ptr, osize, nsize);
}
void* LuaMemTracker::Alloc(void* ptr, size_t osize, size_t nsize) {
if (nsize == 0) {
total_allocated -= osize;
return real_alloc(real_ud, ptr, osize, nsize);
} else {
if (limit && (total_allocated - osize + nsize > limit)) {
return nullptr; // over limit
}
void* newptr = real_alloc(real_ud, ptr, osize, nsize);
if (newptr) {
total_allocated = total_allocated - osize + nsize;
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
write_log();
#endif
}
return newptr;
}
}
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
void LuaMemTracker::write_log() {
if (!log_file) return;
time_t now = time(nullptr);
struct tm* tm_info = localtime(&now);
char time_buf[32];
std::strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tm_info);
if (total_allocated > max_used)
max_used = total_allocated;
if (limit)
std::fprintf(log_file, "%s | used = %zu bytes | max_used = %zu bytes | limit = %zu\n",
time_buf, total_allocated, max_used, limit);
else
std::fprintf(log_file, "%s | used = %zu bytes | max_used = %zu bytes | limit = unlimited\n",
time_buf, total_allocated, max_used);
std::fflush(log_file); // 确保实时写入磁盘
}
#endif
#ifndef LUA_MEM_TRACKER_H
#define LUA_MEM_TRACKER_H
#include <cstdlib>
#include <cstddef>
#include <lua.h>
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
#include <ctime> // time_t
#include <cstdio> // FILE*, fopen, fprintf
#endif
class LuaMemTracker {
public:
LuaMemTracker(lua_Alloc real_alloc, void* real_ud, size_t mem_limit = 0);
~LuaMemTracker();
static void* AllocThunk(void* ud, void* ptr, size_t osize, size_t nsize);
void* Alloc(void* ptr, size_t osize, size_t nsize);
size_t get_total() const { return total_allocated; }
size_t get_limit() const { return limit; }
private:
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
FILE* log_file = nullptr;
void write_log();
#endif
lua_Alloc real_alloc;
void* real_ud;
size_t total_allocated = 0;
size_t limit = 0;
#ifdef YGOPRO_LOG_LUA_MEMORY_SIZE
size_t max_used = 0; // for logging purposes, to track peak memory usage
#endif
};
#endif // LUA_MEM_TRACKER_H
...@@ -15,7 +15,15 @@ ...@@ -15,7 +15,15 @@
#include "interpreter.h" #include "interpreter.h"
interpreter::interpreter(duel* pd): coroutines(256) { interpreter::interpreter(duel* pd): coroutines(256) {
lua_state = luaL_newstate(); lua_State* tmp_L = luaL_newstate(); // 只是为了拿默认 alloc
lua_Alloc raw_alloc;
void* raw_ud;
raw_alloc = lua_getallocf(tmp_L, &raw_ud);
lua_close(tmp_L);
mem_tracker = new LuaMemTracker(raw_alloc, raw_ud, YGOPRO_LUA_MEMORY_SIZE);
lua_state = lua_newstate(LuaMemTracker::AllocThunk, mem_tracker);
current_state = lua_state; current_state = lua_state;
pduel = pd; pduel = pd;
std::memcpy(lua_getextraspace(lua_state), &pd, LUA_EXTRASPACE); //set_duel_info std::memcpy(lua_getextraspace(lua_state), &pd, LUA_EXTRASPACE); //set_duel_info
...@@ -144,6 +152,7 @@ interpreter::interpreter(duel* pd): coroutines(256) { ...@@ -144,6 +152,7 @@ interpreter::interpreter(duel* pd): coroutines(256) {
} }
interpreter::~interpreter() { interpreter::~interpreter() {
lua_close(lua_state); lua_close(lua_state);
delete mem_tracker;
} }
void interpreter::register_card(card *pcard) { void interpreter::register_card(card *pcard) {
if (!pcard) if (!pcard)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <cstdio> #include <cstdio>
#include "LuaMemTracker.h"
class card; class card;
struct card_data; struct card_data;
...@@ -54,6 +55,7 @@ public: ...@@ -54,6 +55,7 @@ public:
int32_t call_depth; int32_t call_depth;
int32_t disable_action_check; int32_t disable_action_check;
int32_t preloaded; int32_t preloaded;
LuaMemTracker* mem_tracker = nullptr;
explicit interpreter(duel* pd); explicit interpreter(duel* pd);
~interpreter(); ~interpreter();
...@@ -100,4 +102,8 @@ public: ...@@ -100,4 +102,8 @@ public:
#define COROUTINE_YIELD 2 #define COROUTINE_YIELD 2
#define COROUTINE_ERROR 3 #define COROUTINE_ERROR 3
#ifndef YGOPRO_LUA_MEMORY_SIZE
#define YGOPRO_LUA_MEMORY_SIZE 0
#endif
#endif /* INTERPRETER_H_ */ #endif /* INTERPRETER_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment