This is related to MMO Performance except that question is about bandwidth. This is about cpu load.
I put together a simple FPS using node.js and webGL. It's extremely simple, a lot like the BuddyMaze clone of MIDI Maze. There's very little going on, everyone moves in two dimensions (no height), shoots simple projectiles, and runs into walls.
Right now, if I make multiple connections to the server where every player shoots rapidly while spinning in circles, I can get about 15 - 20 players in the game before the server maxes out a core and slows way down. And this is when running at 30 fps on the server. At 10 fps, I get about 25 - 30 connections. This is pretty bad, since the game is going to have a lot more to do soon and I'll need to fit more players for this to be a feasible endeavor.
My brother just pointed out some stats about his coworker's TF2 server. His server is lower specs than ours, yet it runs TF2, obviously a much more complex game, at a whopping 500 ticks per second, with 36 users per core. Also, we currently consume much more bandwidth than they do, but we haven't been trying to lower that much yet.
How is this possible? What sort of tricks are there to increase server performance to this magnitude? Some things that I know of include:
- Lowering framerate on the server, and interpolate positions on the client. I got some benefit, but clearly the TF2 server doesn't even bother with this.
- Doing expensive things like collision detection on the client, and verify it infrequently on the server. I haven't moved this over just yet, I will tonight. Even so I don't expect such an enormous gain.
- Break the playing field into regions (quad trees) to minimize calculations. Haven't had an opportunity for this yet.
- I've considered the unfortunate possibility that node.js is just way slower than whatever TF2 is using, and may not be suited for this kind of high intensity task.
- Is it all in the server configuration magic?
So what are the other tricks of the industry to do only the minimum required on the server but still have a flawless game experience? There's a big conflict between "defer to client to save cpu time" and "don't trust the client", so maybe it helps to know where the line is drawn in various situations?
Update
Profiling really is the only mantra I've ever found that's absolutely infallible. I quickly wrapped some timing functions around my code (thanks, FP!) and discovered what I never expected: the act of broadcasting the data to clients accounts for nearly all of the execution time. Specifically, around 90% of it. Further testing showed that this time is dependent on both the number of clients and the size of the data, but more so the latter. On a 20 user load, I cut my broadcast time 90%, from 24ms down to just over 2ms by sending only "{}" instead of the full data. But with only 5 users, broadcasting takes around 0.5 ms. So I clearly need to do some optimization here.
The first most obvious improvement is line of sight checking. This would decrease both the number of people who care about data, and also the amount of data sent to interested parties. Are there other tricks in this realm I can try, which focus on minimizing the cost of my broadcast operation?