realtime-multiplayer-in-html5 icon indicating copy to clipboard operation
realtime-multiplayer-in-html5 copied to clipboard

Exchange protocol too verbose for real world use

Open jgamedev opened this issue 8 years ago • 11 comments

For production deployment it's paramount that data exchange between the client and the server is kept to a minimum. Currently there seems to be zero optimization on this area. For reference here's an example of an exchange payload with only 1 user inside the game room:

"onServerUpdate",{"serverTime":30.091000000001493,"ownPlayer":{"id":"a8061581-7929-4b37-9477-c472e8959634","name":"jay","lastInputSeq":"121","position":{"x":156.355,"y":119.995},"fireing":false,"reloading":false},"players":[],"events":[]}] as {"type":2,"nsp":"/","data":["onServerUpdate",{"serverTime":30.091000000001493,"ownPlayer":{"id":"a8061581-7929-4b37-9477-c472e8959634","name":"jay","lastInputSeq":"121","position":{"x":156.355,"y":119.995},"fireing":false,"reloading":false},"players":[],"events":[]}]}

Here's a few ways in which I believe this could be optimized:

  1. Rounding-off time to a meaningful precision: this is the most obvious one. For instance: ' ' 30.091000000001493 could be sent as 30.091 or (maybe 30.02?) and specially the rounding off of positions could be a benefit in a scenario where there are +20 players in the same room.

  2. Client UIDs should not be included on frequent exchanges: UIDs should be only be included in meaningful, one-time-off events such as joining rooms, etc. After that a much shorter id can be used that can be mapped to the actual client UID whenever that is needed

  3. Avoid sending 'state of the world' types of updates inside of frequent exchanges: instead only "diffs" should be send.

jgamedev avatar Jul 03 '16 18:07 jgamedev

Thanks for pointing out!

arjanfrans avatar Jul 03 '16 18:07 arjanfrans

I would use binary data like agar.io On 3 Jul 2016 14:24, "Arjan Frans" [email protected] wrote:

Thanks for pointing out!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/arjanfrans/realtime-multiplayer-in-html5/issues/10#issuecomment-230167608, or mute the thread https://github.com/notifications/unsubscribe/ABLfznfu82wWAkW4f7S-ucl8RIP8UnQuks5qR_5wgaJpZM4JD60N .

jptosso avatar Jul 03 '16 18:07 jptosso

@asdfuken : that sounds awesome but how does it affect your debugging capabilities? Do you have a way to revert back to normal characters when running in test mode?

jgamedev avatar Jul 03 '16 18:07 jgamedev

I have made a huge modification to messaging, but I would have to documentate the changes :C http://pastebin.com/hCBvk8q7 this is how it's made

2016-07-03 14:42 GMT-04:00 jgamedev [email protected]:

@asdfuken https://github.com/asdfuken : that sounds awesome but how does it affect your debugging capabilities? Do you have a way to revert back to normal characters when running in test mode?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/arjanfrans/realtime-multiplayer-in-html5/issues/10#issuecomment-230168455, or mute the thread https://github.com/notifications/unsubscribe/ABLfzs1AyU6DEZoWcnMx7_cojITpLxUhks5qSAJ6gaJpZM4JD60N .

jptosso avatar Jul 03 '16 18:07 jptosso

@asdfuken , thanks for sharing! I translated the comments in your pastebin into English in case any non-spanish speaking ppl are interested: (http://pastebin.com/nesHjmxZ)

jgamedev avatar Jul 03 '16 18:07 jgamedev

@asdfuken , I like how you use ws, I think you have moved away from socket.io, if that's the case can you comment on that?

Here's some more information I have been able to collect about binary protocols:

  • Article discussing the use of binary protocols in the context of a Node multiplayer game: (http://buildnewgames.com/optimizing-websockets-bandwidth/) (Warning! Probably outdated because it predates Socket.io binary support)
  • bops provides a common API on top of Node Buffers and client side TypedArrays
  • Conversion from/to UTF-8 is supposed to be slow.. so maybe stay away from that?
  • Socket.io blog on adding support for the Buffer type. Binary is so powerful that in his experiment guy is piping in whole game frames (actual pngs!) and using the browser like a VNC client. :scream: Crazy stuff!

jgamedev avatar Jul 03 '16 21:07 jgamedev

My protocol is based on that http://agar.gcommer.com/index.php?title=Protocol I use binary because I wont transfer blops data, binary is enough :) For Strings I use this function

var Uint32ArrayToString = function(data, offset)
{
  var s = "";
  for(var i = offset; i< data.length;i++)
  {
    s += String.fromCharCode(data[i]);
  }
  return s;
}

And I init the server with

var WebSocketServer = require('ws').Server
  , wss = new WebSocketServer({ port: 8001 });
wss.binaryType = 'arraybuffer'; //IMPORTANT!!!!!

Those are ascii encoded

jptosso avatar Jul 03 '16 22:07 jptosso

I am thinking about some sort of compress function that transforms the original object to the most minimal possible and then only send the diff. Then on the other side a decompress function will convert it back to a usable object and it then applies the diff to the previously received state.

arjanfrans avatar Jul 04 '16 19:07 arjanfrans

@arjanfrans , binary has a extremely small footprint so you would not need to diff it, unless you need to reduce message frequency as opposed to payload size.

jgamedev avatar Jul 05 '16 02:07 jgamedev

@arjanfrans , binary has a extremely small footprint so you would not need to diff it, unless you need to reduce message frequency as opposed to payload size.

jgamedev avatar Jul 05 '16 02:07 jgamedev

I tried something with sending the diffs only and converting those to binary.

https://github.com/arjanfrans/realtime-multiplayer-in-html5/pull/13/commits/6141375f1167426ed142ce8b354da4c09898bbf4

arjanfrans avatar Aug 08 '16 11:08 arjanfrans