Question about Nagles Algorithm, and what it means for me

So, my current client/server approach is to use sockets, C# 4.0 on the server side. I create a packet of information with a packet type (player movement, player get item, etc) which consists of one byte.

What follows is the serialized information for the actual data/parameters. I serialize and deserialize the information on my own, using the BinaryWriter and BinaryReader.

My initial effort has consisted of something like this:

Client → Server: Server_PickupItem, Id XXXX

Server does the processing on its end. Verifies the player actually CAN pick the item up, transfers ownership, etc.

Server → Client: Client_PickUpItem, Id xxxx

Client does its thing…the visual change of the player picking up the item.

My question:
This works fine…so far. My mind was wandering, and thinking about optimizations. The actual pickup item data may be small…like 5 bytes, and sending these out immediately is a waste…that’s 5 bytes each way PLUS the TCP/IP packet overhead. Why not queue up the requests for a player, and only send them out every X milliseconds…reducing bandwidth? So every 100 milliseconds, I send up all of the requests queued up. For a small number of players, I don’t see it making much difference.

For a LOT of players, I think it could be huge.

I realized this sounded familiar…this is what the Nagles algorithm does, apparently.

So, my question is…would I just be duplicating the Nagles stuff by doing this on my end? Each player would have a dedicated queue of packet data on the server. If it sounds like a good idea, any suggestions on implementation?

I was thinking of running this on a separate thread, where it just continually checks all player data queued up to see if it’s time to pump it out. I guess one downside would be…it would add 100 milliseconds or so to latency.

Any thoughts or suggestions on this would be very welcome.

In general TCP/IP for networking is not a good idea unless you know exactly what you’re doing, I suppose the same applies for UDP - but when people say that for example WoW used TCP/IP, while true they were only able to do so because of the extremely clever tricks they do to hide the lag, things that are very time-consuming to build yourself.

But in short, for TPC/IP:

  1. Never us nagles
  2. Group things yourself

Also, dont use binarywriter/binaryreader, write your own stream class that works on the bit level instead of byte level. You’re wasting huge amounts of space dealing in bytes as your smallest unit.

Interesting…I hadn’t thought of this, I actually thought I was doing pretty good by using the binary writer and reader.

Do you mean, convert the outgoing bytes into a stream of bits, and compress those? Sorry, I’m not clear on how you would send data from .Net primitives, as a stream of bits in a meaningful way.

I mean…if I have a value which can only go from 0 to 15, yeah I could send 4 bits. But it seems like creating the bit representation and just sending those 4 bits would cost more than just sending out a byte.

If you think in terms of just one item/a few bits, yes, it seems wasteful. But when you end up sending 8 booleans, that take 8 bytes instead of 1 byte (1 bit per bool) you realize why you’d do this.

Oh, yeah I already use some of this…some of the properties of my items/entities are booleans. I pack them into bytes. I just wasn’t sure how I would do this meaningfully with other data types.

Thanks, fholm

It’s not too hard - here’s a quick prototype:

http://stackoverflow.com/questions/11979184/reading-bit-aligned-data/11979287#11979287

TBH though, I wouldn’t worry about bit level optimizations until everything else is done. Odds are the data saved isn’t going to make/break the game, and it can come at some CPU cost.