Forum

Idea - Throttling the Server

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Idea - Throttling the Server

Postby mh » Thu Sep 09, 2010 5:49 pm

This has evolved kind of organically, so excuse the fact that it's slightly messy at the moment.
Code: Select all
void Host_ServerFrame (void)
{
   qboolean sv_runphysics = false;
   static float sv_hosttime = 666;
   float sv_physicstime;

   // run the world state
   pr_global_struct->frametime = host_frametime;

   // set the time and clear the general datagram
   SV_ClearDatagram ();

   // check for new clients
   SV_CheckForNewClients ();

   // read client messages
   SV_RunClients ();

   sv_hosttime += host_frametime;

   // prevent the user from setting this too slow
   if (sv_serverthrottle.value > 0 && sv_serverthrottle.value < 20)
      Cvar_SetValue ("sv_serverthrottle", 20);

   if (sv_serverthrottle.value > 0)
   {
      float servertime = (1.0f / sv_serverthrottle.value);

      if (host_frametime >= servertime)
      {
         sv_runphysics = true;
         sv_hosttime = 0;
         sv_physicstime = host_frametime;
      }
      else if (sv_hosttime >= servertime)
      {
         sv_runphysics = true;
         sv_hosttime = 0;
         sv_physicstime = servertime;
      }
      else sv_runphysics = false;
   }
   else
   {
      sv_runphysics = true;
      sv_hosttime = host_frametime;
      sv_physicstime = host_frametime;
   }

   if (sv_runphysics)
   {
      float sv_savedtime = host_frametime;

      host_frametime = sv_physicstime;

      // move things around and think
      // always pause in single player if in console or menus
      if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game))
         SV_Physics ();

      host_frametime = sv_savedtime;
   }

   // send all messages to the clients
   SV_SendClientMessages ();
}

The idea here is to restrict the server (specifically physics and entity thinking) to a fixed framerate, so that if we are running faster (by setting a maxfps cvar, for example), we don't get weird physics glitches. It's not 100% robust but hopefully if we put our heads together we'll get it near enough for all practical purposes. ;)

Note that the client is always run and client messages always happen, so the percieved smoothness from running at a higher framerate doesn't (or at least shouldn't) go away.

Note also that if we're running slow we skip the throttling step and just always run anyway.

Of course it's in no way preferable to doing proper FPS-independent physics, but the timers in Quake are such a mess with so many different variables stashed all over the place that something like this is more accessible to the community as a whole.

It also has the nice bonus that it can relieve the CPU overhead of mods which may have very intensive QC (which can easily cut your framerate in half, even on a modern machine).

I've tested it on a few well-known trouble spots such as the lifts and plats in e1m1, the first YA secret in e1m4, and various slope edges, and it seems to behave as it should (i.e. as if we were running at 72 FPS), but I think it needs a good shake-down and some constructive criticism from you lot before it can go out as a tutorial, hence the fact that I'm posting it here.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Baker » Thu Sep 09, 2010 6:07 pm

Something that serves as a solid option to get Quake's physics "normalized" is definitely needed.

I don't have anything useful to add at the moment, but intermittently I've been trying to get a good handle on client and server timing. Which at least in GLQuake is inconsistent as hell.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby ceriux » Thu Sep 09, 2010 6:34 pm

sounds pretty awesome i dont know much if anything about engine coding though. in lamens what exactly is it doing ? also is there any down sides to this once implemented? i looked through the code you posted and i may be wrong but what ever it does do seems to affect single and multiplayer. if so what would be the differences when playering single versus multiplayer?
User avatar
ceriux
 
Posts: 2223
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Postby mh » Thu Sep 09, 2010 7:04 pm

It won't affect MP because you won't have a local server (this function only runs if there is a local server running) and the remote server will have it's own framerate set which it runs at. You can verify this for yourself by running an engine is a debugger, setting a breakpoint anywhere in that function, and connecting to a server.

Note the following in the vanilla Quake source:
Code: Select all
if (sv.active)
   Host_ServerFrame ();

That, by the way, is also the reason why setting a high cl_/host_/pq_maxfps doesn't cause physics glitches in MP games (and also why people who predominantly play MP tend to report these physics glitches as "bugs" whenever they run an SP map).

This code is therefore strictly for SP games where there is a local server running. One MP scenario it would affect is if you were running a listen server but in such a case throttling the server to 72 FPS would also be desirable, so it's irrelevant.

if you're doubly paranoid you can always add a check for maxclients > 1 to the code above and revert to default behaviour if so, but you'd be wasting your time.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby mh » Fri Sep 10, 2010 1:31 am

I did say it needed some shaking down. :D

The "if (sv_runphysics)" needs to change to this:
Code: Select all
    if (sv_runphysics)
    {
        float sv_savedtime = host_frametime;

        host_frametime = sv_physicstime;
        pr_global_struct->frametime = host_frametime;

        // move things around and think
        // always pause in single player if in console or menus
        if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game))
            SV_Physics ();

        host_frametime = sv_savedtime;
        pr_global_struct->frametime = host_frametime;
    }
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby andrewj » Fri Sep 10, 2010 3:54 am

I think you could do the same thing with simpler code by using a variable which marks the point in time when to run the physics.

For example:
Code: Select all
if (sv_hosttime >= sv_physicstime)
{
  double step = 1.0 / sv_serverthrottle;
  double time = sv_hosttime - sv_physicstime + step;
  SV_Physics(time);
  sv_physicstime = sv_hosttime + step;
}
andrewj
 
Posts: 133
Joined: Mon Aug 30, 2010 3:29 pm
Location: Australia

Postby r00k » Fri Sep 10, 2010 3:59 am

Oddly I was doing something similar this very morning with the particle engine, whereas if I go to higher FPS then particles get overdrawn: smoke trails get thicker, flames are more robust etc. What's the point of higher fps if it makes the particle engine work harder? Which in turn makes the fps suffer more..
I tried putting a timer on it only to get strobing particles (the drawing was only staggered), which lead me to making a fake client frame in host.c, which in turn updates the screen refresh. My results were false positives, and humorous - timerefresh progressed over 3000fps :P
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby qbism » Fri Sep 10, 2010 4:54 pm

Should sv_serverthrottle really be a cvar, or just cap at max(min(cl_maxfps.value, 72), 20) ?
User avatar
qbism
 
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am

Postby mh » Fri Sep 10, 2010 5:33 pm

qbism wrote:Should sv_serverthrottle really be a cvar, or just cap at max(min(cl_maxfps.value, 72), 20) ?

That's a really good point. I just made it a cvar because it was the instinctive/unthinking thing to do, but now that you mention it, the Quake engine is designed to run at a maximum of 72 FPS and there is a very strong argument to be made in favour of locking the server speed at that rate.

@andrewj - I'll compare your code with mine shortly, but it does seem more sensible. I did say that mine had evolved organically... :lol:

These two are exactly the reason why I put this out for discussion, by the way. Keep it coming! :D
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Spirit » Fri Sep 10, 2010 9:27 pm

Excellent idea. I really do not like how Quake uses so much CPU.
Darkplaces does it nicely. It can even cap even more if its window loses focus.
Improve Quaddicted, send me a pull request: https://github.com/SpiritQuaddicted/Quaddicted-reviews
Spirit
 
Posts: 1031
Joined: Sat Nov 20, 2004 9:00 pm

Postby mh » Fri Sep 10, 2010 10:26 pm

It will always use 100% CPU (or 100% of a core) even with this, and that's just the nature of a game loop, and is actually a highly desirable trait in a game loop. Anything that spins constantly without a sleep each iteration will chew your CPU, even this:
Code: Select all
while (1);
The reason why it's desirable is so that the code can react as soon as possible to unpredictable events, such as when the user is going to press a mouse button or a key. As the very least you need to spin while retrieving time.

I've seen working examples where the coder has tried sending a game to sleep for a bit through each iteration of the loop, out of a mistaken idea that using less CPU is somehow a good thing, and to be honest the only end result is jerky input and inconsistent performance. A game is one type of app where you most definitely do want to be using as much CPU as you possibly can. that's the definition of a "real time application". You need that CPU to be constantly busy doing stuff. Believe me, people have written books about this, it's a given, accepted fact.

So it doesn't relieve CPU usage (and it shouldn't); what it does do is (attempt to) make server timings consistent irrespective of framerate, but only for framerates higher than 72. Lower framerates will still be the same as before.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby mankrip » Sat Sep 11, 2010 2:50 am

The only thing I'm not sure here is where does the knowledge of 72 fps being the official framerate of Quake comes from.

The only time-related code I've found while searching through the source code for the number 72 was this:
Code: Select all
    if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)
        return false;        // framerate is too high

... which they may have added because the vertical refresh of the CRT monitors at the time probably couldn't go higher than 72 Hz. Running the game faster than that may give some physics glitches, but I'm not sure if these aren't just the result of lack of proper hardware to test the game at higher framerates at the time.

So, Quake's physics was (incorrectly) designed to take advantage of higher framerates, but I don't see this as an indication of the highest possible framerate at the time being somewhat official.

On the other hand, there's plenty of evidence in favor of Quake having being designed with a 10 fps gameplay in mind - it's also the minimum framerate at which the engine will allow the game to run in real time, but the fact is that I don't remember anything in the whole game or in the engine being set to run faster than that, even when they could - an example are the countless "self.nextthink = time + 0.1;" throughout the QC code that could have been set to a smaller interval without breaking anything when running at 10 fps.

This is not the case with some mods that actually needs faster framerates, of course. But I see it as an indication that there's no need to run the game at 72 fps by default.

Values of 20, 25, 40 or 50 fps would give plenty of frames for any mod to run, and can be nicely divided.

Anyway, this solution is really interesting. I'll test it to see how a value of 10 fps will make things behave when I get around to implementing it. This could be helpful to leave more CPU time to the renderer when running on the Dreamcast.
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
User avatar
mankrip
 
Posts: 915
Joined: Fri Jul 04, 2008 3:02 am

Postby frag.machine » Sat Sep 11, 2010 3:08 am

mh wrote:It will always use 100% CPU (or 100% of a core) even with this, and that's just the nature of a game loop, and is actually a highly desirable trait in a game loop. Anything that spins constantly without a sleep each iteration will chew your CPU, even this:
Code: Select all
while (1);
The reason why it's desirable is so that the code can react as soon as possible to unpredictable events, such as when the user is going to press a mouse button or a key. As the very least you need to spin while retrieving time.

I've seen working examples where the coder has tried sending a game to sleep for a bit through each iteration of the loop, out of a mistaken idea that using less CPU is somehow a good thing, and to be honest the only end result is jerky input and inconsistent performance. A game is one type of app where you most definitely do want to be using as much CPU as you possibly can. that's the definition of a "real time application". You need that CPU to be constantly busy doing stuff. Believe me, people have written books about this, it's a given, accepted fact.

So it doesn't relieve CPU usage (and it shouldn't); what it does do is (attempt to) make server timings consistent irrespective of framerate, but only for framerates higher than 72. Lower framerates will still be the same as before.


Agreed 100%. A game is usually a full screen app that consumes all the attention from the user, so it's fair it uses as much resources as it can hogs from the CPU.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby qbism » Sat Sep 11, 2010 4:51 am

mk wrote:Quake's physics was (incorrectly) designed to take advantage of higher framerates

Given the gravity fix, I wonder what the threshold of perception is for physics fps. If a typical player can't notice the difference between 50fps and 72fps, might as well cap at 50. (50 is just an example)
User avatar
qbism
 
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am

Postby goldenboy » Sat Sep 11, 2010 11:13 am

There might be existing mods that have tweaked their fps-dependant physics to work best at around 72 fps. Grappling hooks are an example.

It should be ensured that existing mods still behave correctly.
User avatar
goldenboy
 
Posts: 924
Joined: Fri Sep 05, 2008 11:04 pm
Location: Kiel

Next

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest