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 <bones_was_here@xonotic.au>
delta = Sys_DirtyTime() - time0;
if (delta < 0 || delta >= 1800)
delta = 0;
delta = Sys_DirtyTime() - time0;
if (delta < 0 || delta >= 1800)
delta = 0;
- host.sleeptime += delta;
+ host.sleeptime = delta;
// R_TimeReport("sleep");
return;
}
// R_TimeReport("sleep");
return;
}
if (sleeptime >= 1)
Host_Sleep(sleeptime);
if (sleeptime >= 1)
Host_Sleep(sleeptime);
+ else
+ host.sleeptime = 0;
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
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;
qbool restless; // don't sleep
qbool paused; // global paused state, pauses both client and server
cmd_buf_t *cbuf;
qbool changelevel_issued;
/// server infostring
char serverinfo[MAX_SERVERINFO_STRING];
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;
// csqc stuff
unsigned char *csqc_progdata;
protocolversion_t protocol;
double time;
protocolversion_t protocol;
double time;
+ 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;
// used by PF_checkclient
int lastcheck;
double lastchecktime;
// set up the new server
//
memset (&sv, 0, sizeof(sv));
// 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;
// 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;
*/
const char *SV_TimingReport(char *buf, size_t buflen)
{
*/
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;
}
extern cvar_t host_maxwait;
char vabuf[1024];
qbool playing = false;
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;
+
- 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;
// 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)));
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;
if (sv_timer > 0.1)
{
if (!svs.threaded)
if (sv_timer > 0.1)
{
if (!svs.threaded)
- svs.perf_acc_lost += (sv_timer - 0.1);
+ sv.perf_acc_lost += (sv_timer - 0.1);
offset = 0;
offset += sv_timer;
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
}
// only advance time if not paused
if (sv_timer >= 0)
{
if (!svs.threaded)
if (sv_timer >= 0)
{
if (!svs.threaded)
- svs.perf_acc_lost += sv_timer;
+ sv.perf_acc_lost += sv_timer;
sv_timer += sv_deltarealtime;
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();
// 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();
{
// don't accumulate time for the first 10 seconds of a match
// so things can settle
{
// 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)));
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;
time0 = Sys_DirtyTime();
Sys_Sleep((int)wait);
delta = Sys_DirtyTime() - time0;if (delta < 0 || delta >= 1800) delta = 0;
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;
if(advancetime > 0)
{
offset = sv_timer + (Sys_DirtyTime() - sv_realtime); // LadyHavoc: FIXME: I don't understand this line
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
}
// only advance time if not paused
// if there is some time remaining from this frame, reset the timers
if (sv_timer >= 0)
{
// 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;