Advertisement

Possible optimizations?

Started by May 25, 2006 09:36 PM
7 comments, last by HopeDagger 18 years, 8 months ago
Well, I'm just a tad bit erked at the network performance of my current game. And yes, I know I'm starting off vague. [grin] Here's some of the background details: Currently I'm developing an online 2D shooter, Skirmish Online. I'm using plain 'ol Winsock for the networking, with the UDP/IP protocol. I'd really appreciate some suggestions on improving my networking methods. What I'd like to know is, what's a reasonable in/out bytes-per-second flow and packets-per-second for an online action game of sorts? Here's a printout from my debuglog on a few different numbers of players. (3-8)

Players     = 3
Packets In  = 10
Packets Out = 10
Bandwidth In  = 216 B/s
Bandwidth Out = 705 B/s

Players     = 4
Packets In  = 15
Packets Out = 15
Bandwidth In  = 319 B/s
Bandwidth Out = 1381 B/s

Players     = 5
Packets In  = 19
Packets Out = 19
Bandwidth In  = 419 B/s
Bandwidth Out = 2272 B/s

Players     = 6
Packets In  = 24
Packets Out = 24
Bandwidth In  = 512 B/s
Bandwidth Out = 3211 B/s

Players     = 7
Packets In  = 29
Packets Out = 29
Bandwidth In  = 619 B/s
Bandwidth Out = 4327 B/s

Players     = 8
Packets In  = 31
Packets Out = 33
Bandwidth In  = 710 B/s
Bandwidth Out = 5674 B/s

At 4 update per second per player, I don't think 32/pps is that bad, is it? What numbers do most online games deal with? At 8 players on Cable internet most players' ping reaches up to 300-600ms or higher, and at 4 players only about 100-200ms. This still seems pretty high considering my connection. Comparing to games like, say, CounterStrike, where with 20 players the ping only starts to go up over 250ms. Anyways, the gist of my network code is: -> One non-blocking UDP socket on the server's end. Every frame it checks for new data via recvfrom(). Handles new players and existing player updates through there. -> One non-blocking UDP socket on the client's end. Calls recv() every frame to get new data from the server. Handles data appropriately. -> Data is sent by accumulating into one packet over a variable duration. I have it set at 250ms, which means 4 packets of information. Sizes range from 70-200 bytes based on the players online. Is this reasonable? -> Data is received by iterating over all of the subpackets contained in the one overall received packet. Does anything seem 'off' about any of this? I'm running on a Cable connection with an upload of over 26 KB/s, so I don't see why I'm having such slowdown at just 5.5 KB/s. And I apologize in advance if this comes off sounding more like a whining post than an inquiry for advice sort of post. I'm just borked about the whole thing because I've boggled my mind on it and I can't figure out how so many games are getting away with much more dataflow-per-second and having such nice latency times. [grin] Thanks in advance for any advice/tips/comments!
I'm not really sure what the problem is here... what kind of numbers were you expecting to see for say, the 8 players case?
Advertisement
Quote:
Original post by zppz
I'm not really sure what the problem is here... what kind of numbers were you expecting to see for say, the 8 players case?


That's moreso the question I'm asking, hehe. I'm showing the numbers I'm getting, and the connection I'm on, and what method I'm using for my networking, and asking if the numbers seem to be about right. It seems like virtually every other (quasi-)commercial online game I play sees more players and much better latency times, even on the same connection as me or worse. :-/

I again apologize for my vagueness. Basically I'm just a little disappointed about the performance and I'm grasping at straws on here hoping for somesort of tip/edge that I'm missing that will help beef up the performance. [grin]
When I play Counter-strike Source, ping is seldom over 50, even on servers with 20 players. I typically play on servers that are pretty close, and well hosted, though.

I have no idea what your connection is, so how can I tell whether your numbers are good or not?

What I can say is that a typical action shooter type game needs at least 10 packets per second to not feel sluggish to the players. More is better. You typically allow sending more packets before you've received an ack for the previous packet. Your role as a client is to continually update the server with the player actions. The server's role is to continually update each client with the data for all the other players.

If you can only shoot things that are "near" then you can probably reduce some bandwidth usage by sending updates for things that are "far away" for each client at a lower rate.

Using a very simple control scheme, for a 2D game, I'd allocate something like this (per player):

4 bits -- player ID (16 players max)
4 bits -- active shot count (15 shots max)
16 bits -- x pos
16 bits -- y pos
6 bits -- hitpoints
10 bits -- orientation (heading)
12 bits -- velocity x
12 bits -- velocity y
foreach shot:
16 bits -- x pos
16 bits -- y pos
6 bits -- shot type (gives velocity) (explosion is a special type)
10 bits -- orientation

At 10 Hz, this would give you 100 bytes per player per second for position updates, and an additional 60 bytes per shot per second per active shot. Add 280 bytes for UDP header overhead for 10 packets (you send all players in a single packet each time). Let's assume 9 players and 12 active shots, for a total of 1800 bytes per second (you don't echo data back to the original player). You then have to multiply that by 9 again to get the server upstream bandwidth requirement, which would then be 16200 bytes per second.

It's slightly un-clear what you're actually asking for -- does this help?
enum Bool { True, False, FileNotFound };
Quote:
Original post by hplus0603
I have no idea what your connection is, so how can I tell whether your numbers are good or not?


To be fair, I did mention that I'm on a Cable connection, which is generally a pretty reasonable speed. (100+ down, 26+ up)

Quote:
What I can say is that a typical action shooter type game needs at least 10 packets per second to not feel sluggish to the players. More is better.


Quote:
Let's assume 9 players and 12 active shots, for a total of 1800 bytes per second (you don't echo data back to the original player). You then have to multiply that by 9 again to get the server upstream bandwidth requirement, which would then be 16200 bytes per second.


Exactly. You're suggesting such numbers, which are WAY higher than what I'm pushing in/out, and yet I'm getting very disappointing performance on a connection that should be able to handle such low in/out amounts. This is why I'm so darn perplexed. [smile]

Generally, I've got most of your suggestions already down. There is player update and bullet culling -- that is, not sending data to players outside the range that such updates would effect them -- and my update/bullet packets resemble your suggested ones closely enough.

Quote:
It's slightly un-clear what you're actually asking for -- does this help?


The advice/suggestions are definitely appreciated, but I was moreso after any possible explanations as to why, with numbers so much smaller than even you're recommending -- I'm only using 4 updates per second, and have about 7KB/s out with 9 players -- I'm getting such great latency on all of the players.

I again apologize for my vagueness, hehe. [smile]
This might be a stupid question, but how are you determining your clients' ping? If the ping packets are being caught up in the packet aggregation process that will add an average latency of half the aggregate length (i.e. around 250ms).
Advertisement
Quote:
Original post by Bob Janova
This might be a stupid question, but how are you determining your clients' ping? If the ping packets are being caught up in the packet aggregation process that will add an average latency of half the aggregate length (i.e. around 250ms).


Hehe, yes I had that issue when I first implemented the packet accumulation system, but the timestamp that is 'ping/pong'd already accounts for the accumulation delay. Therefore I'm confident that my numbers are accurate.
If you send a packet only 3 times a second, that will automatically give you the effects of a 300 ms latency (which, typically, would be considered "ping").

If you "ping" one of the clients from the command line, while you're also running the game, what does "ping" tell you? This test might help separate out your code from the networking infrastructure as possibly culprits.

Are you getting packet loss? Your upstream may not be at all what you think it is.

Last, cable providers are notorious for not providing high quality IP service. I wouldn't be surprised if they are gating your traffic in some piece of their hardware, just because you're UDP, or you're on a port they don't explicitly optimize for.
enum Bool { True, False, FileNotFound };
Quote:
Original post by hplus0603
If you "ping" one of the clients from the command line, while you're also running the game, what does "ping" tell you? This test might help separate out your code from the networking infrastructure as possibly culprits.

Are you getting packet loss? Your upstream may not be at all what you think it is.

Last, cable providers are notorious for not providing high quality IP service. I wouldn't be surprised if they are gating your traffic in some piece of their hardware, just because you're UDP, or you're on a port they don't explicitly optimize for.


Thanks for the insightful tips and ideas, hplus. I'll take a closer look at all of these. [smile]

This topic is closed to new replies.

Advertisement