From 039df0d38bbae893a56eacd437f05034fdc9e1ea Mon Sep 17 00:00:00 2001 From: namishere Date: Fri, 10 Feb 2023 21:34:50 -0800 Subject: [PATCH 1/3] Implement perfstats options for LUAh_PreThinkFrame and LUAh_PostThinkFrame --- src/d_netcmd.c | 2 +- src/lua_hook.h | 2 + src/lua_hooklib.c | 31 ++++++++--- src/m_perfstats.c | 134 ++++++++++++++++++++++++++++++++++++++-------- src/m_perfstats.h | 4 ++ src/p_tick.c | 8 ++- 6 files changed, 151 insertions(+), 30 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f63f38a74..8c122e56a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -376,7 +376,7 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); static CV_PossibleValue_t perfstats_cons_t[] = { - {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; + {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {4, "PreThinkFrame"}, {5, "PostThinkFrame"}, {0, NULL}}; consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange); static CV_PossibleValue_t ps_samplesize_cons_t[] = { {1, "MIN"}, {1000, "MAX"}, {0, NULL}}; diff --git a/src/lua_hook.h b/src/lua_hook.h index 4fa3a1a17..fea234f2f 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -126,7 +126,9 @@ int LUA_HookPlayer(player_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); int LUA_HookKey(event_t *event, int hook); // Hooks for key events +void LUA_HookPreThinkFrame(void); void LUA_HookThinkFrame(void); +void LUA_HookPostThinkFrame(void); int LUA_HookMobjLineCollide(mobj_t *, line_t *); int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher); int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index c4083c9ad..e00860dfb 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -671,10 +671,8 @@ void LUA_HookHUD(int hook_type, huddrawlist_h list) SPECIALIZED HOOKS ========================================================================= */ -void LUA_HookThinkFrame(void) +static void hook_think_frame(int type) { - const int type = HOOK(ThinkFrame); - // variables used by perf stats int hook_index = 0; precise_t time_taken = 0; @@ -692,7 +690,7 @@ void LUA_HookThinkFrame(void) { get_hook(&hook, map->ids, k); - if (cv_perfstats.value == 3) + if (cv_perfstats.value >= 3) { lua_pushvalue(gL, -1);/* need the function again */ time_taken = I_GetPreciseTime(); @@ -700,12 +698,18 @@ void LUA_HookThinkFrame(void) call_single_hook(&hook); - if (cv_perfstats.value == 3) + if (cv_perfstats.value >= 3) { lua_Debug ar; time_taken = I_GetPreciseTime() - time_taken; lua_getinfo(gL, ">S", &ar); - PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + if (type == 4) // sorry for magic numbers + PS_SetPreThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + else if (type == 5) + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + else if (type == 6) + PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; } } @@ -714,6 +718,21 @@ void LUA_HookThinkFrame(void) } } +void LUA_HookPreThinkFrame() +{ + hook_think_frame(HOOK(PreThinkFrame)); +} + +void LUA_HookThinkFrame() +{ + hook_think_frame(HOOK(ThinkFrame)); +} + +void LUA_HookPostThinkFrame() +{ + hook_think_frame(HOOK(PostThinkFrame)); +} + int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) { Hook_State hook; diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 9f65a7616..935df82ac 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -65,7 +65,10 @@ static ps_metric_t ps_removecount = {0}; ps_metric_t ps_checkposition_calls = {0}; +ps_metric_t ps_lua_prethinkframe_time = {0}; ps_metric_t ps_lua_thinkframe_time = {0}; +ps_metric_t ps_lua_postthinkframe_time = {0}; + ps_metric_t ps_lua_mobjhooks = {0}; ps_metric_t ps_otherlogictime = {0}; @@ -157,7 +160,9 @@ perfstatrow_t gamelogic_rows[] = { {" mobjs ", " Mobjs: ", &ps_thlist_times[THINK_MOBJ], PS_TIME|PS_LEVEL}, {" dynslop", " Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE], PS_TIME|PS_LEVEL}, {" precip ", " Precipitation: ", &ps_thlist_times[THINK_PRECIP], PS_TIME|PS_LEVEL}, + {" lprethinkf", " LUAh_PreThinkFrame:", &ps_lua_prethinkframe_time, PS_TIME|PS_LEVEL}, {" lthinkf", " LUAh_ThinkFrame:", &ps_lua_thinkframe_time, PS_TIME|PS_LEVEL}, + {" lpostthinkf", " LUAh_PostThinkFrame:", &ps_lua_postthinkframe_time, PS_TIME|PS_LEVEL}, {" other ", " Other: ", &ps_otherlogictime, PS_TIME|PS_LEVEL}, {0} }; @@ -192,10 +197,43 @@ int ps_frame_index = 0; int ps_tick_index = 0; // dynamically allocated resizeable array for thinkframe hook stats +ps_hookinfo_t *prethinkframe_hooks = NULL; +int prethinkframe_hooks_length = 0; +int prethinkframe_hooks_capacity = 16; + ps_hookinfo_t *thinkframe_hooks = NULL; int thinkframe_hooks_length = 0; int thinkframe_hooks_capacity = 16; +ps_hookinfo_t *postthinkframe_hooks = NULL; +int postthinkframe_hooks_length = 0; +int postthinkframe_hooks_capacity = 16; + +void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) +{ + if (!prethinkframe_hooks) + { + // array needs to be initialized + prethinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity, PU_STATIC, NULL); + } + if (index >= prethinkframe_hooks_capacity) + { + // array needs more space, realloc with double size + int new_capacity = prethinkframe_hooks_capacity * 2; + prethinkframe_hooks = Z_Realloc(prethinkframe_hooks, + sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL); + // initialize new memory with zeros so the pointers in the structs are null + memset(&prethinkframe_hooks[prethinkframe_hooks_capacity], 0, + sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity); + prethinkframe_hooks_capacity = new_capacity; + } + prethinkframe_hooks[index].time_taken.value.p = time_taken; + memcpy(prethinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char)); + // since the values are set sequentially from begin to end, the last call should leave + // the correct value to this variable + prethinkframe_hooks_length = index + 1; +} + void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) { if (!thinkframe_hooks) @@ -221,6 +259,31 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) thinkframe_hooks_length = index + 1; } +void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) +{ + if (!postthinkframe_hooks) + { + // array needs to be initialized + postthinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity, PU_STATIC, NULL); + } + if (index >= postthinkframe_hooks_capacity) + { + // array needs more space, realloc with double size + int new_capacity = postthinkframe_hooks_capacity * 2; + postthinkframe_hooks = Z_Realloc(postthinkframe_hooks, + sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL); + // initialize new memory with zeros so the pointers in the structs are null + memset(&postthinkframe_hooks[postthinkframe_hooks_capacity], 0, + sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity); + postthinkframe_hooks_capacity = new_capacity; + } + postthinkframe_hooks[index].time_taken.value.p = time_taken; + memcpy(postthinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char)); + // since the values are set sequentially from begin to end, the last call should leave + // the correct value to this variable + postthinkframe_hooks_length = index + 1; +} + static boolean PS_HighResolution(void) { return (vid.width >= 640 && vid.height >= 400); @@ -564,7 +627,9 @@ void PS_UpdateTickStats(void) ps_tictime.value.p - ps_playerthink_time.value.p - ps_thinkertime.value.p - - ps_lua_thinkframe_time.value.p; + ps_lua_prethinkframe_time.value.p - + ps_lua_thinkframe_time.value.p - + ps_lua_postthinkframe_time.value.p; PS_CountThinkers(); } @@ -576,21 +641,24 @@ void PS_UpdateTickStats(void) PS_UpdateRowHistories(misc_calls_rows, false); } } - if (cv_perfstats.value == 3 && cv_ps_samplesize.value > 1 && PS_IsLevelActive()) + if (cv_ps_samplesize.value > 1) { - int i; - for (i = 0; i < thinkframe_hooks_length; i++) + if(cv_perfstats.value >= 3 && PS_IsLevelActive()) { - PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + int i; + for (i = 0; i < thinkframe_hooks_length; i++) + { + PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + } + } + if (cv_perfstats.value) + { + ps_tick_index++; + if (ps_tick_index >= cv_ps_samplesize.value) + ps_tick_index = 0; + if (ps_tick_samples_left) + ps_tick_samples_left--; } - } - if (cv_perfstats.value && cv_ps_samplesize.value > 1) - { - ps_tick_index++; - if (ps_tick_index >= cv_ps_samplesize.value) - ps_tick_index = 0; - if (ps_tick_samples_left) - ps_tick_samples_left--; } } @@ -610,7 +678,7 @@ static void PS_DrawDescriptorHeader(void) int samples_left = max(ps_frame_samples_left, ps_tick_samples_left); int x, y; - if (cv_perfstats.value == 3) + if (cv_perfstats.value >= 3) { x = 2; y = 0; @@ -697,7 +765,7 @@ static void PS_DrawGameLogicStats(void) PS_DrawPerfRows(x, y, V_PURPLEMAP, misc_calls_rows); } -static void PS_DrawThinkFrameStats(void) +static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook) { char s[100]; int i; @@ -711,7 +779,7 @@ static void PS_DrawThinkFrameStats(void) PS_DrawDescriptorHeader(); - for (i = 0; i < thinkframe_hooks_length; i++) + for (i = 0; i < hook_length; i++) { #define NEXT_ROW() \ @@ -724,7 +792,7 @@ if (y > 192) \ break; \ } - char* str = thinkframe_hooks[i].short_src; + char* str = hook[i].short_src; char* tempstr = tempbuffer; int len = (int)strlen(str); char* str_ptr; @@ -771,7 +839,7 @@ if (y > 192) \ if (len > 20) str += len - 20; snprintf(s, sizeof s - 1, "%20s: %d", str, - PS_GetMetricScreenValue(&thinkframe_hooks[i].time_taken, true)); + PS_GetMetricScreenValue(&hook[i].time_taken, true)); V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); NEXT_ROW() @@ -780,6 +848,21 @@ if (y > 192) \ } } +static void PS_DrawPreThinkFrameStats(void) +{ + draw_think_frame_stats(prethinkframe_hooks_length, prethinkframe_hooks); +} + +static void PS_DrawThinkFrameStats(void) +{ + draw_think_frame_stats(thinkframe_hooks_length, thinkframe_hooks); +} + +static void PS_DrawPostThinkFrameStats(void) +{ + draw_think_frame_stats(postthinkframe_hooks_length, postthinkframe_hooks); +} + void M_DrawPerfStats(void) { if (cv_perfstats.value == 1) // rendering @@ -793,7 +876,7 @@ void M_DrawPerfStats(void) // tics when frame skips happen PS_DrawGameLogicStats(); } - else if (cv_perfstats.value == 3) // lua thinkframe + else if (cv_perfstats.value >= 3) // lua thinkframe { if (!PS_IsLevelActive()) return; @@ -802,13 +885,22 @@ void M_DrawPerfStats(void) // Low resolutions can't really use V_DrawSmallString that is used by thinkframe stats. // A low-res version using V_DrawThinString could be implemented, // but it would have much less space for information. - V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Perfstats 3 is not available"); + V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Lua Perfstats is not available"); V_DrawThinString(80, 100, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "for resolutions below 640x400."); + return; } - else + if (cv_perfstats.value == 3) { PS_DrawThinkFrameStats(); } + else if (cv_perfstats.value == 4) + { + PS_DrawPreThinkFrameStats(); + } + else if (cv_perfstats.value == 5) + { + PS_DrawPostThinkFrameStats(); + } } } diff --git a/src/m_perfstats.h b/src/m_perfstats.h index f6a7c1f74..c70e7ad30 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -43,12 +43,16 @@ extern ps_metric_t ps_thlist_times[]; extern ps_metric_t ps_checkposition_calls; +extern ps_metric_t ps_lua_prethinkframe_time; extern ps_metric_t ps_lua_thinkframe_time; +extern ps_metric_t ps_lua_postthinkframe_time; extern ps_metric_t ps_lua_mobjhooks; extern ps_metric_t ps_otherlogictime; +void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); +void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); void PS_UpdateTickStats(void); diff --git a/src/p_tick.c b/src/p_tick.c index fe6a4d33f..2db2ab59d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -664,7 +664,9 @@ void P_Ticker(boolean run) ps_lua_mobjhooks.value.i = 0; ps_checkposition_calls.value.i = 0; - LUA_HOOK(PreThinkFrame); + PS_START_TIMING(ps_lua_prethinkframe_time); + LUA_HookPreThinkFrame(); + PS_STOP_TIMING(ps_lua_prethinkframe_time); PS_START_TIMING(ps_playerthink_time); for (i = 0; i < MAXPLAYERS; i++) @@ -768,7 +770,9 @@ void P_Ticker(boolean run) if (modeattacking) G_GhostTicker(); - LUA_HOOK(PostThinkFrame); + PS_START_TIMING(ps_lua_postthinkframe_time); + LUA_HookPostThinkFrame(); + PS_STOP_TIMING(ps_lua_postthinkframe_time); } if (run) From eaacb64d3fa4f9fa17159aea19fbc6da9c24f4d3 Mon Sep 17 00:00:00 2001 From: namishere Date: Sat, 11 Feb 2023 04:19:24 -0800 Subject: [PATCH 2/3] Update PS_UpdateTickStats to correctly update metric history for pre and post thinkframe hooks --- src/m_perfstats.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 935df82ac..ce5202e7d 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -646,9 +646,20 @@ void PS_UpdateTickStats(void) if(cv_perfstats.value >= 3 && PS_IsLevelActive()) { int i; - for (i = 0; i < thinkframe_hooks_length; i++) + if (cv_perfstats.value == 3) { - PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + for (i = 0; i < thinkframe_hooks_length; i++) + PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + } + else if (cv_perfstats.value == 4) + { + for (i = 0; i < prethinkframe_hooks_length; i++) + PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false, false); + } + else if (cv_perfstats.value == 5) + { + for (i = 0; i < postthinkframe_hooks_length; i++) + PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false, false); } } if (cv_perfstats.value) From b404c965a6e3d73dc8903cc2f3c99b00578e385d Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 26 Oct 2023 09:47:50 +0000 Subject: [PATCH 3/3] Update lua_hooklib.c You need to "void" the functions --- src/lua_hooklib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 00237217d..2e17a0dea 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -718,17 +718,17 @@ static void hook_think_frame(int type) } } -void LUA_HookPreThinkFrame() +void LUA_HookPreThinkFrame(void) { hook_think_frame(HOOK(PreThinkFrame)); } -void LUA_HookThinkFrame() +void LUA_HookThinkFrame(void) { hook_think_frame(HOOK(ThinkFrame)); } -void LUA_HookPostThinkFrame() +void LUA_HookPostThinkFrame(void) { hook_think_frame(HOOK(PostThinkFrame)); }