Tips for saving bandwidth (post your own!)

Started by
3 comments, last by hplus0603 18 years, 10 months ago
Hopefully if enough people reply with ideas this will get stickied or added to the FAQ. Here we go... Floating Point Values o There is very rarely a good reason to send a double over the network. o Cut 32bit floats to 24bit whenever possible. Vectors o The minimum amount of data you need to send for a vector is 3 bits (yes), and the maximum is 51 (using 32-24 bit reduction). This is achieved by putting a 3 bit header at the start. Values of 0-3 only require the header to be sent as logic can be used to work out all 3 values, while 4-6 will require two floating point values. You can pick and choose which values to send (XY, XZ or YZ). The missing value can be worked out using some vector math which I can't remember at this point (will post it here later). 0: X + Y + Z = 0.0 (no more data, X, Y and Z are set to 0.0) 1: X = 1.0 (no more data, Y and Z are set to 0.0) 2: Y = 1.0 (no more data, X and Z are set to 0.0) 3: Z = 1.0 (no more data, X and Y are set to 0.0) 4: X and Y sent (2 24-bit floats sent) 5: X and Z sent (2 24-bit floats sent) 6: Y and Z sent (2 24-bit floats sent) o Angles - A lot of game objects only turn on a single axis (the vertical), so there is no need to send the other two values. o Angles - Do you really need 24-bits precision? You can encode it into an unsigned short and save 8 bits or go even smaller and use 15bit, 14bit, 13bit, etc data types.

// Assumes angle is in the range of 0 <= angle < 360
unsigned short AngleToShort (const float float_angle)
{
    // Need to check for float_angle == 0.0f?
    return (unsigned short) float_angle / 360.0f * 65535.0f;
}

float ShortToAngle (const unsigned short short_angle)
{
    if (short_angle == 65535)
        return 0.0f;

    else
        return (float) short_angle / 65535.0f * 360.0f;
}

Those two functions can be optimized a lot further (the divisions replaced with multiplication and then the two multiplications precalculated). If using a smaller data size (15bit, 14bit, etc) then replace 65535.0f with the maximum number that can be stored in those bits. That's all I can think of for now as I'm rather tired. I hope you all share some of your secrets (or even common wisdom) so everyone can learn. Feel free to point out mistakes in the above too :).
Advertisement
Why are you so worried about sending small amounts of data. As long as you only send 1500 bytes or so (one packet) it is going to take the same amount of time.

Seems to be that you would be better off waiting till you had ~1500 bytes and sending a packet full of info, rather than a bunch of small packets. If your game/program can handle waiting a little longer before transfering data.
Quote: As long as you only send 1500 bytes or so (one packet) it is going to take the same amount of time


This isn't about sending a bunch of small packets, but sening packets with as much information crammed in them as possible to save bandwidth.

Sure, the packet size will be the same, but it won't carry the same amount of information. If you can compress you data by 30%, that's 30% more information that is in the 1.5 kb packet and thus 30% less bandwidth I have to pay for...I'm sending more information in a shorter amount of time and paying less money for it too.

My only hint is to never forget to institute a "send only if delta" routine for your network traffic.... that messages should only be sent if something has changed (a state, a position, an animation) and not on a fixed schedule (such as if(new_vector != old_vector){send_vector_update()}else{return;}.
Common sense. :)
What exactly do you mean by 24-bit float? Do you scale it and just send the mantissa or something?
-Mike
All that advice reduces to "encode your numeric values using the coarsest representation you can accept." That's the simplest way of trimming the fat from your packets, but not the best. You can use other mechanisms such as state-dependent compression (such as "delta packets" used in Q3) and even evolutionary dictionary-based compression (such as suggested by Jon Blow in his Game Developer article series) to pack your data even tighter.

The smallest data, however, is data that you don't have to send at all. If you co-simulate your entities on client and server, you only need to send controller input, which is a few buttons, rather than position/velocity/orientation, which is some number of floating-point values. If you can wait to batch up your updates into a single packet, you will use less bandwidth for framing overhead.

Never send data that the other end already knows. Pre-calculate what you can and refer to it implicitly in the network packet.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement