From: bones_was_here Date: Sun, 30 Jul 2023 18:45:56 +0000 (+1000) Subject: Properly reset server timers and perf stats after level change X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=d3b8dc6b859c81a72fa1ea2cccb5064a319c32fc;p=xonotic%2Fdarkplaces.git Properly reset server timers and perf stats after level change This prevents the server running "catchup" physics frames immediately after level change (when sv_maxphysicsframesperserverframe > 1) and makes accurate stats available almost immediately (all 0 before that). Moves perf stats from persistent to temporary storage. Signed-off-by: bones_was_here --- diff --git a/host.c b/host.c index 1929ebad..d2725cc2 100644 --- a/host.c +++ b/host.c @@ -694,7 +694,7 @@ static inline void Host_Sleep(double time) delta = Sys_DirtyTime() - time0; if (delta < 0 || delta >= 1800) delta = 0; - host.sleeptime += delta; + host.sleeptime = delta; // R_TimeReport("sleep"); return; } @@ -748,6 +748,8 @@ void Host_Main(void) if (sleeptime >= 1) Host_Sleep(sleeptime); + else + host.sleeptime = 0; } return; diff --git a/host.h b/host.h index 109948c5..6c4f5f60 100644 --- a/host.h +++ b/host.h @@ -23,7 +23,7 @@ typedef struct host_static_s unsigned int framecount; // incremented every frame, never reset (checked by Host_Error and Host_SaveConfig_f) double realtime; // the accumulated mainloop time since application started (with filtering), without any slowmo or clamping double dirtytime; // the main loop wall time for this frame, equal to Sys_DirtyTime() at the start of this host frame - double sleeptime; // time spent sleeping overall + double sleeptime; // time spent sleeping after the last frame qbool restless; // don't sleep qbool paused; // global paused state, pauses both client and server cmd_buf_t *cbuf; diff --git a/server.h b/server.h index 5dfe2ac0..d1cdb1ab 100644 --- a/server.h +++ b/server.h @@ -34,20 +34,6 @@ typedef struct server_static_s qbool changelevel_issued; /// server infostring char serverinfo[MAX_SERVERINFO_STRING]; - // performance data - float perf_cpuload; - float perf_lost; - float perf_offset_avg; - float perf_offset_max; - float perf_offset_sdev; - // temporary performance data accumulators - float perf_acc_realtime; - float perf_acc_sleeptime; - float perf_acc_lost; - float perf_acc_offset; - float perf_acc_offset_squared; - float perf_acc_offset_max; - int perf_acc_offset_samples; // csqc stuff unsigned char *csqc_progdata; @@ -88,9 +74,25 @@ typedef struct server_s protocolversion_t protocol; double time; - double frametime; + unsigned int spawnframe; // signals SV_Frame() to reset its timers + + // performance data + float perf_cpuload; + float perf_lost; + float perf_offset_avg; + float perf_offset_max; + float perf_offset_sdev; + // temporary performance data accumulators + float perf_acc_realtime; + float perf_acc_sleeptime; + float perf_acc_lost; + float perf_acc_offset; + float perf_acc_offset_squared; + float perf_acc_offset_max; + int perf_acc_offset_samples; + // used by PF_checkclient int lastcheck; double lastchecktime; diff --git a/sv_main.c b/sv_main.c index 35b61233..9c5707f4 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1891,6 +1891,10 @@ void SV_SpawnServer (const char *map) // set up the new server // memset (&sv, 0, sizeof(sv)); + + // tell SV_Frame() to reset its timers + sv.spawnframe = host.framecount; + // if running a local client, make sure it doesn't try to access the last // level's data which is no longer valiud cls.signon = 0; @@ -2504,7 +2508,7 @@ Returns a time report string, for example for */ const char *SV_TimingReport(char *buf, size_t buflen) { - return va(buf, buflen, "%.1f%% CPU, %.2f%% lost, offset avg %.1fms, max %.1fms, sdev %.1fms", svs.perf_cpuload * 100, svs.perf_lost * 100, svs.perf_offset_avg * 1000, svs.perf_offset_max * 1000, svs.perf_offset_sdev * 1000); + return va(buf, buflen, "%.1f%% CPU, %.2f%% lost, offset avg %.1fms, max %.1fms, sdev %.1fms", sv.perf_cpuload * 100, sv.perf_lost * 100, sv.perf_offset_avg * 1000, sv.perf_offset_max * 1000, sv.perf_offset_sdev * 1000); } extern cvar_t host_maxwait; @@ -2516,42 +2520,39 @@ double SV_Frame(double time) char vabuf[1024]; qbool playing = false; + // reset timer after level change + if (host.framecount == sv.spawnframe || host.framecount == sv.spawnframe + 1) + sv_timer = time = host.sleeptime = 0; + if (!svs.threaded) { - svs.perf_acc_sleeptime = host.sleeptime; - svs.perf_acc_realtime += time; + sv.perf_acc_sleeptime += host.sleeptime; + sv.perf_acc_realtime += time; // Look for clients who have spawned for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++) if(host_client->begun && host_client->netconnection) playing = true; - if(svs.perf_acc_realtime > 5) + if(sv.perf_acc_realtime > 5) { - svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime; - svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime; + sv.perf_cpuload = 1 - sv.perf_acc_sleeptime / sv.perf_acc_realtime; + sv.perf_lost = sv.perf_acc_lost / sv.perf_acc_realtime; - if(svs.perf_acc_offset_samples > 0) + if(sv.perf_acc_offset_samples > 0) { - svs.perf_offset_max = svs.perf_acc_offset_max; - svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples; - svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg); + sv.perf_offset_max = sv.perf_acc_offset_max; + sv.perf_offset_avg = sv.perf_acc_offset / sv.perf_acc_offset_samples; + sv.perf_offset_sdev = sqrt(sv.perf_acc_offset_squared / sv.perf_acc_offset_samples - sv.perf_offset_avg * sv.perf_offset_avg); } - if(svs.perf_lost > 0 && developer_extra.integer && playing) // only complain if anyone is looking + if(sv.perf_lost > 0 && developer_extra.integer && playing) // only complain if anyone is looking Con_DPrintf("Server can't keep up: %s\n", SV_TimingReport(vabuf, sizeof(vabuf))); - } - if(svs.perf_acc_realtime > 5 || sv.time < 10) - { - /* - * Don't accumulate time for the first 10 seconds of a match - * so things can settle - */ - svs.perf_acc_realtime = svs.perf_acc_sleeptime = - svs.perf_acc_lost = svs.perf_acc_offset = - svs.perf_acc_offset_squared = svs.perf_acc_offset_max = - svs.perf_acc_offset_samples = host.sleeptime = 0; + sv.perf_acc_realtime = sv.perf_acc_sleeptime = + sv.perf_acc_lost = sv.perf_acc_offset = + sv.perf_acc_offset_squared = sv.perf_acc_offset_max = + sv.perf_acc_offset_samples = 0; } /* @@ -2577,7 +2578,7 @@ double SV_Frame(double time) if (sv_timer > 0.1) { if (!svs.threaded) - svs.perf_acc_lost += (sv_timer - 0.1); + sv.perf_acc_lost += (sv_timer - 0.1); sv_timer = 0.1; } @@ -2621,12 +2622,12 @@ double SV_Frame(double time) offset = 0; offset += sv_timer; - ++svs.perf_acc_offset_samples; - svs.perf_acc_offset += offset; - svs.perf_acc_offset_squared += offset * offset; + ++sv.perf_acc_offset_samples; + sv.perf_acc_offset += offset; + sv.perf_acc_offset_squared += offset * offset; - if(svs.perf_acc_offset_max < offset) - svs.perf_acc_offset_max = offset; + if(sv.perf_acc_offset_max < offset) + sv.perf_acc_offset_max = offset; } // only advance time if not paused @@ -2676,7 +2677,7 @@ double SV_Frame(double time) if (sv_timer >= 0) { if (!svs.threaded) - svs.perf_acc_lost += sv_timer; + sv.perf_acc_lost += sv_timer; sv_timer = 0; } @@ -2706,7 +2707,7 @@ static int SV_ThreadFunc(void *voiddata) sv_timer += sv_deltarealtime; - svs.perf_acc_realtime += sv_deltarealtime; + sv.perf_acc_realtime += sv_deltarealtime; // at this point we start doing real server work, and must block on any client activity pertaining to the server (such as executing SV_SpawnServer) SV_LockThreadMutex(); @@ -2722,22 +2723,22 @@ static int SV_ThreadFunc(void *voiddata) { // don't accumulate time for the first 10 seconds of a match // so things can settle - svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0; + sv.perf_acc_realtime = sv.perf_acc_sleeptime = sv.perf_acc_lost = sv.perf_acc_offset = sv.perf_acc_offset_squared = sv.perf_acc_offset_max = sv.perf_acc_offset_samples = 0; } - else if(svs.perf_acc_realtime > 5) + else if(sv.perf_acc_realtime > 5) { - svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime; - svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime; - if(svs.perf_acc_offset_samples > 0) + sv.perf_cpuload = 1 - sv.perf_acc_sleeptime / sv.perf_acc_realtime; + sv.perf_lost = sv.perf_acc_lost / sv.perf_acc_realtime; + if(sv.perf_acc_offset_samples > 0) { - svs.perf_offset_max = svs.perf_acc_offset_max; - svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples; - svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg); + sv.perf_offset_max = sv.perf_acc_offset_max; + sv.perf_offset_avg = sv.perf_acc_offset / sv.perf_acc_offset_samples; + sv.perf_offset_sdev = sqrt(sv.perf_acc_offset_squared / sv.perf_acc_offset_samples - sv.perf_offset_avg * sv.perf_offset_avg); } - if(svs.perf_lost > 0 && developer_extra.integer) + if(sv.perf_lost > 0 && developer_extra.integer) if(playing) Con_DPrintf("Server can't keep up: %s\n", SV_TimingReport(vabuf, sizeof(vabuf))); - svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0; + sv.perf_acc_realtime = sv.perf_acc_sleeptime = sv.perf_acc_lost = sv.perf_acc_offset = sv.perf_acc_offset_squared = sv.perf_acc_offset_max = sv.perf_acc_offset_samples = 0; } // get new packets @@ -2762,7 +2763,7 @@ static int SV_ThreadFunc(void *voiddata) time0 = Sys_DirtyTime(); Sys_Sleep((int)wait); delta = Sys_DirtyTime() - time0;if (delta < 0 || delta >= 1800) delta = 0; - svs.perf_acc_sleeptime += delta; + sv.perf_acc_sleeptime += delta; continue; } @@ -2780,11 +2781,11 @@ static int SV_ThreadFunc(void *voiddata) if(advancetime > 0) { offset = sv_timer + (Sys_DirtyTime() - sv_realtime); // LadyHavoc: FIXME: I don't understand this line - ++svs.perf_acc_offset_samples; - svs.perf_acc_offset += offset; - svs.perf_acc_offset_squared += offset * offset; - if(svs.perf_acc_offset_max < offset) - svs.perf_acc_offset_max = offset; + ++sv.perf_acc_offset_samples; + sv.perf_acc_offset += offset; + sv.perf_acc_offset_squared += offset * offset; + if(sv.perf_acc_offset_max < offset) + sv.perf_acc_offset_max = offset; } // only advance time if not paused @@ -2822,7 +2823,7 @@ static int SV_ThreadFunc(void *voiddata) // if there is some time remaining from this frame, reset the timers if (sv_timer >= 0) { - svs.perf_acc_lost += sv_timer; + sv.perf_acc_lost += sv_timer; sv_timer = 0; } }