🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How can I optimize Linux server for lowest latency game server?

Started by
29 comments, last by hplus0603 8 years ago

Could I just send 2-3 repetitive UDP packets instead of your solution?


No, I would not expect that to be particularly helpful.

this kinda breaks a little bit


That may perhaps be an indication that you don't yet have time management down in your distributed simulation engine.

Minecraftian levels of wrong


Exactly. Clearly, there is an existence proof that some games have this problem! Make sure yours is not one of them :-)
enum Bool { True, False, FileNotFound };
Advertisement

Could I just send 2-3 repetitive UDP packets instead of your solution?


No, I would not expect that to be particularly helpful.

Could you please talk a little bit more about it? At this moment, I am quite afraid, that UDP update packet will bloat up enormously if I include all the shots for 5 times. Some weapons can shoot 10 times a second and there could be ~12 players. Or should I not be?

And could you tell me why would my method of just sending everyone shot event UDP packet for 2-3 times instead of 1 TCP packet not work?

Game I'm making - GANGFORT, Google Play, iTunes

Could I just send 2-3 repetitive UDP packets instead of your solution?


No, I would not expect that to be particularly helpful.


Could you please talk a little bit more about it? At this moment, I am quite afraid, that UDP update packet will bloat up enormously if I include all the shots for 5 times. Some weapons can shoot 10 times a second and there could be ~12 players. Or should I not be?

And could you tell me why would my method of just sending everyone shot event UDP packet for 2-3 times instead of 1 TCP packet not work?


Forum FAQ item #12, what to put in packets and how often to send them. In your case, two links apply, read this and this.

The nutshell version is to keep accumulating data and resend until data is acknowledged, but there is a bit more to it.

Forum FAQ item #12, what to put in packets and how often to send them. In your case, two links apply, read this and this.

The nutshell version is to keep accumulating data and resend until data is acknowledged, but there is a bit more to it.

I understand it, but it does not help. I know accumulating data and resending until ack would be the best option, but we are talking about some less time consuming options:

1. include shot event data in periodical update packet for 5 times in a row(if he will not receive any of these packets, then screw him, he probably has ping way > 100 or unstable connection).

2. instead of using sendTCP for each shot event, use sendUDP but 2 or 3 times, to reduce the chance of packet loss.

Game I'm making - GANGFORT, Google Play, iTunes

TCP is bad for games, because if any packet is lost, any packets that are sent after the lost packet are delayed until the first packet can be resent.
This is great for file transfers, okay for streaming songs and movies where you can read-ahead by 10-20 seconds, and terrible for anything where dozens of milliseconds count.

Sending the same UDP datagram three times will quite likely use much more bandwidth than just including the same message more than once in successive scheduled packets.
This is obvious from summing up the data size involved. (Remember: UDP over IP has a minimum packet overhead of 28 bytes, plus whatever framing overhead you add for player ID, sequencing, etc.)
Also, sending the same packet three times in a row right after each other is unlikely to help in case of packet loss, because packet loss is not random-per-packet. If a switch is temporarily overloaded and dropping packets for 20 milliseconds, then all three packets arriving one after the other will all be dropped, whereas the next scheduled packet arriving 30 or 50 milliseconds later has a much higher chance of making it.

I'm assuming that you're already following common best practices such as counting simulation steps, rather than floating time, fixing your simulation step size to a known duration, and tagging commands with the step number at which the player initially initiated them.
I also assume that you follow the pattern of sending one packet containing any and all pending messages, plus some general connection/game management information and framing, on a fixed interval (e g at 20 Hz.)
If you have an action game and are doing something different, then you are likely not going to get the most optimal game networking experience across a variety of players. There's a reason all successful networked games pretty much use this model, with very slight tweaks!
enum Bool { True, False, FileNotFound };

I also assume that you follow the pattern of sending one packet containing any and all pending messages

Not really. There is just an update packet from both sides being spammed by UDP and some very important packets come through TCP, that do not really happen so often(except shot event, but I'm going to fix it). I did not have time to implement packet loss detection and could not afford to lose them, so I chose this way.

Okay, I get the reason now, thank you. But another option could be to send it 3 times in a row, but with e.g. 5-10ms pause in between. What do you think about it?I 'm thinking which solution would produce the least nasty code without too much time spent implementing it.

Game I'm making - GANGFORT, Google Play, iTunes

1. include shot event data in periodical update packet for 5 times in a row(if he will not receive any of these packets, then screw him, he probably has ping way > 100 or unstable connection).

2. instead of using sendTCP for each shot event, use sendUDP but 2 or 3 times, to reduce the chance of packet loss.

Always resending a fixed time doesn't handle it.

Why 5 for the periodical update?

Why "2 or 3" for sending an event?

If you chose five, what happens if a network disruption drops the next five packets and the sixth goes through? Alternatively, if it goes through perfectly the first time, why resend four unnecessary times? Same with events, why resend two or three times if once is enough, and why two or three if it might be the fourth time that goes through?

Why not 4? or 7? or 92? Or why not just 1, since the vast majority of time UDP gets through perfectly? Pulling numbers out of the ether does not help.

There is a known solution: Resend until acknowledged.

In the general case of networking the UDP packet will arrive quickly. Unless you have a particularly chatty interface, the data will arrive and the server will send a response back to you acknowledging it before your game needs to send another packet. Most games accumulate data for a short time window then send it off.

Effectively this pattern implements a sliding window similar to what you get in TCP, except you are not using TCP's stop-until-resent functionality, you always resend until the other side says they've got it.

If there is high latency or connectivity issue it may get sent multiple times before you hear back, but if the data is fairly small and you are on high speed networks the impact is minimal. While it is important to consider size a few bytes doesn't hurt if the game has requirements for megabit connections.

In the general case for well-designed protocols there will be a full round trip with acknowledgement of the data all the time.

But another option could be to send it 3 times in a row, but with e.g. 5-10ms pause in between. What do you think about it?I 'm thinking which solution would produce the least nasty code without too much time spent implementing it.


No, I think that would generate much messier code.

It sounds like the structure of your outgoing messages queue isn't helping you solve the problem. Perhaps you should update your code until the easy thing to do is the right thing to do?
enum Bool { True, False, FileNotFound };

Okay, thank you, I have implemented it. So now instead of sending lots of TCP events, I include them into a periodical UDP update packet for 5 times in a row. If a player fails to receive any of these 5, then screw him, I do not resend it, he probably has ping too high anyway. And some critical but quite more rare events are still being sent through TCP. I do not have time to implement acknowledging and resending, so will leave that for the future.

This TCP problem is now solved, so back to the topic. I have also ordered a dedicated server from Google Cloud.

What can I do for my Linux server to minimize latency as much as possible? Are there any config params?

Game I'm making - GANGFORT, Google Play, iTunes

a game server for my mobile game


Also, on mobile data, you'll see significant latency from the network. Switching to WiFi will improve things, but you're never going to match wired.

What can I do for my Linux server to minimize latency as much as possible?


Make sure it never reaches 100% load. Note that in "top," there is 100% per hardware thread, so if you have a hyper-threaded 12-core machine, you'd have 24 hardware threads, 12 cores, and you wouldn't want total CPU load to reach or exceed 1200%.

I don't know if Java 8 still has these options, but if it does: run with the "interactive" GC rather than the "server" GC because the "server" GC is batch-optimized, not latency-optimized.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement