Scaling

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Scaling

Post by Baker »

What prevents a single player coop server with 200 players and 1000 monsters on a BSP2-ish map running a DarkPlaces or FTE Quakeworld like protocol?

Would it be the QuakeC where 1000 monsters trying to determine what players they can see? Is this a design flaw of QuakeC where really once per frame the server should determine what MONSTERS the CLIENTS can see INSTEAD they can see and those monsters be notified?

Or are there other bottlenecks?
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 ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Scaling

Post by Spike »

fte has a special cluster mode (compile with -DCLUSTER) which provides some mapcluster command. This allows the server to fork itself into multiple processes such that each process handles a different map, and with a qc extension it is possible to trade players from one process to another (the original server becomes the entry gateway that also relays messages/players between the other processes).
This allows the server to use 100% of every cpu core on the server.
Potentially it could be tweaked to run the different processes on different physical servers. This would significantly increase total capacity.

200 players in coop is somewhat futile. If you have that many players, you probably won't want them all in one tiny/single map in the first place. Splitting them between multiple servers (each running different maps) is simply the most sane way to handle it. Plus it helps scale beyond the game design's limits, by potentially allowing multiple instances of the same map (required if you want players to experience things at their own pace instead of being forced to stay with the masses just to experience *something*).

coop monsters normally work by checking only if a single player is visible to the monster each frame. with 200 players, this would mean that a monster would wait up to 20 seconds or so before it can see you. Or in other words, a coop server with 200 players needs to stop using the checkclient builtin, which makes things more expensive.

there is a map called helm18 or something, which contains about 10000 knights. I've not tried playing it in coop, but even in single player, the QC is busy doing far too many tracelines etc.

if you want to do mmo-style stuff, you will need to use a cluster of servers to provide both load balancing and game balance. I don't know of any way around that.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Scaling

Post by Baker »

Spike wrote:coop monsters normally work by checking only if a single player is visible to the monster each frame. with 200 players, this would mean that a monster would wait up to 20 seconds or so before it can see you. Or in other words, a coop server with 200 players needs to stop using the checkclient builtin, which makes things more expensive.
That was what I wondering about in particular, at scale would be grossly inefficient.

I need to finish up what I am working on now -- which won't necessarily be quick (walk before you run, etc.).

Wasn't aware FTE had that build option. But I'm not entirely surprised either. :D
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 ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Scaling

Post by Spike »

what you could do is embrace csqc to have the csqc tell the server that the monster should get pissy. this would completely remove all the per-monster logic for idle monsters, and prevent players who are timing out from getting killed. have the csqc do all the animations automatically, possibly even move the monster around somewhat, all clientside. CSQC networking might be kinda convienient here - update the monster's .SendFlags field periodically, and then check who saw the monster inside its SendEntity function.
Scaling to 200 players might be tricky, but if most of the monsters are going to be idle or pvs culled anyway, you won't have some 200*1000 thing going on, but closer to 200+1000. Plus you can optimise players by running player movement clientside to get a load of traceboxes off the server.

there's a lot of tricks you can use to reduce server load. and most of them require completely rethinking aspects of the networking and opening up the server to abundant trivial cheats - especially if the client is open source.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Scaling

Post by Baker »

Spike wrote:Scaling to 200 players might be tricky, but if most of the monsters are going to be idle or pvs culled anyway, you won't have some 200*1000 thing going on, but closer to 200+1000. Plus you can optimise players by running player movement clientside to get a load of traceboxes off the server.
It seems to me that the traceline function, might be inefficient. I don't see it using visibility testing.

Would it be faster if it used map visibility to quickly ruleout entities? Or is that an expensive check in its own right?

Raw thought: What if a list of seen monsters were created per player during SV_WriteEntitiesToClient and that data were used the next frame (or next QuakeC frame)?

I'm trying to think if there is any situation that a monster can see a player that the reverse isn't true.

Since the player count is finite could just do something like
qboolean monster_seen[MAX_PLAYER_SLOTS_200 + 1][MAX_ABSOLUTELY_POSSIBLE_EDICTS_65536]
In server write entities monster_seen[playerslot (+ 1?)] = monster_seen[0] = result (true or false)

Monster think could check monster_seen[self entnum] before even bothering too look around
Spike wrote:there's a lot of tricks you can use to reduce server load. and most of them require completely rethinking aspects of the networking and opening up the server to abundant trivial cheats - especially if the client is open source.
What are the other concepts you have to optimize that expose trivial cheating opportunities to reduce server load?
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 ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Scaling

Post by Spike »

the obvious one is to have player positions determined fully by the client. just have the client send the update origin+angles and the server can omit all the traceboxes required to move the player through the world (this gives teleportation).
you could have the client telling the server that various monsters should become hostile when the player gets close (ie: the client does per-client/monster tracelines instead of the server) (this gives notarget).
you could have the client running full animation. this might cause slight de-syncs, but it shouldn't really be much worse than the server updating every frame individually.
if your idle monsters are meant to roam slightly around some tether point (to give a bit more life to your maps), have the monster's position as some monster.effectiveorigin = monster.roamcenter+CalcRoam(time*monster.roamspeed) function that the client+server are both using, preventing the need for resends. have the client determine angles too. this only really works for idle monsters though, but combined with the client reporting when monsters become hostile this removes ALL load of idle monsters from the server - its value is significant when you have lots of monsters which are too lazy to attack distant players.
you could have the client determine when the missiles the client fired impact upon walls/enemies(aimbot). may have issues when the target goes out of the pvs, but hey. Alternatively you can write your game to determine hit/miss when its first fired, and have the projectile simply a timer that does damage at the precise time, and have the client update positions etc to interpolate from start position to _current_ enemy position so that it impacts at about the right sort of time, but yeah, doesn't always travel at a constant speed.

lots of ways to cheat. either by clients or by the programmer. :P

pvs is nice and fast, assuming it has already been decompressed that is, and assuming you already know the two leafs that you're trying to determine the pvs for too, of course. If you don't already know the two leafs/clusters (q1 vs q3) then you're going to need to walk the bsp tree to find the relevent leaf first anyway. Its basically the same price as pointcontents, so long as you only want the pvs from a single leaf (read: single point). You may need to cache this leaf separately from the regular 'fatpvs' or entleaf_t stuff, as for speed you want to keep things with a single point instead of paying for supporting boxes.
Decompressing the pvs takes more time. QuakeWorld has always stored the pvs decompressed in ram, demonstrating that this can easily be load-time.
the problem is more that the pvs is a rendering optimisation. it is not perfectly tight. if you go with pvs only, you will end up with monsters seeing around corners if the leaf their in extends beyond said corner. For every player that might be in the pvs, your monster will need to use traceline to verify that it is actually visible. Doing that clientside keeps things more scalable (and helps a bit when people lag because of networking overload), but yeah, cheats.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Scaling

Post by Baker »

Spike wrote:pvs is nice and fast, assuming it has already been decompressed that is, and assuming you already know the two leafs that you're trying to determine the pvs for too, of course. If you don't already know the two leafs/clusters (q1 vs q3) then you're going to need to walk the bsp tree to find the relevent leaf first anyway. Its basically the same price as pointcontents, so long as you only want the pvs from a single leaf (read: single point). You may need to cache this leaf separately from the regular 'fatpvs' or entleaf_t stuff, as for speed you want to keep things with a single point instead of paying for supporting boxes.
Decompressing the pvs takes more time. QuakeWorld has always stored the pvs decompressed in ram, demonstrating that this can easily be load-time.
investigation list + 1
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 ..
Post Reply