diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index ccc3c25e7d..29010b8147 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -681,6 +681,10 @@ Miscellaneous both from the curry call and the closure call itself. I.e., ``curry(func,a,b)(c,d)`` equals ``func(a,b,c,d)``. +* ``dfhack.dump_interrupt_timing_data()`` + + Dumps the internal log of times between interrupt callbacks, as a table of integers. + Each entry is the difference between two consecutive interrupts, in microseconds. Locking and finalization ------------------------ diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 56c5079838..06051383f0 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -505,11 +505,19 @@ volatile std::sig_atomic_t lstop = 0; static void interrupt_hook (lua_State *L, lua_Debug *ar); static void interrupt_init (lua_State *L) { - lua_sethook(L, interrupt_hook, LUA_MASKCOUNT, 256); + lua_sethook(L, interrupt_hook, LUA_MASKCOUNT, 16384); } +constexpr auto interrupt_log_buffer_size = 64; +using timer = std::chrono::high_resolution_clock; +static std::array interrupt_log_buffer; +static size_t interrupt_log_buffer_index = 0; + static void interrupt_hook (lua_State *L, lua_Debug *ar) { + interrupt_log_buffer[interrupt_log_buffer_index] = timer::now(); + interrupt_log_buffer_index = (interrupt_log_buffer_index + 1) % interrupt_log_buffer_size; + if (lstop) { lstop = 0; @@ -518,6 +526,24 @@ static void interrupt_hook (lua_State *L, lua_Debug *ar) } } +static int dfhack_dump_interrupt_timing_data(lua_State* L) +{ + int base = lua_gettop(L); + lua_createtable(L, interrupt_log_buffer_size-1, 0); + auto last = timer::now(); + for (auto idx = 0; idx < interrupt_log_buffer_size; idx++) + { + auto i = (idx + interrupt_log_buffer_index) % interrupt_log_buffer_size; + auto dur = interrupt_log_buffer[i] - last; + last = interrupt_log_buffer[i]; + if (idx>0) { + lua_pushinteger(L, std::chrono::duration_cast(dur).count()); + lua_rawseti(L, base + 1, idx); + } + } + return 1; +} + bool DFHack::Lua::Interrupt (bool force) { lua_State *L = DFHack::Core::getInstance().getLuaState(true); @@ -1498,6 +1524,7 @@ static const luaL_Reg dfhack_funcs[] = { { "with_suspend", lua_dfhack_with_suspend }, { "open_plugin", dfhack_open_plugin }, { "curry", dfhack_curry }, + { "dump_interrupt_timing_data", dfhack_dump_interrupt_timing_data }, { NULL, NULL } };