Idea - Throttling the Server
Moderator: InsideQC Admins
18 posts
• Page 1 of 2 • 1, 2
Idea - Throttling the Server
This has evolved kind of organically, so excuse the fact that it's slightly messy at the moment.
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.
- 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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
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.
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?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
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?
-

ceriux - Posts: 2223
- Joined: Sat Sep 06, 2008 3:30 pm
- Location: Indiana, USA
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:
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.
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
I did say it needed some shaking down.
The "if (sv_runphysics)" needs to change to this:
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 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:
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
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
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
- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 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...
These two are exactly the reason why I put this out for discussion, by the way. Keep it coming!
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
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.
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
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:
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.
- Code: Select all
while (1);
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 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:
... 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.
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.
-

mankrip - Posts: 915
- Joined: Fri Jul 04, 2008 3:02 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: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.
- Code: Select all
while (1);
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)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
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)
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
18 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 1 guest
