aomarks / bridgesim

A starship bridge simulator for the web.
https://aomarks.github.io/bridgesim/
16 stars 3 forks source link

host should broadcast deltas instead of full snapshots #4

Closed aomarks closed 8 years ago

aomarks commented 8 years ago

The host currently broadcasts a nearly complete snapshot of the entity database to clients 15 times a second. Each client has an incoming data rate of 300-500 kB/sec. That's too high.

Refactor systems to emit database mutation objects instead of directly updating the database. The host can then easily also broadcast those mutations to clients.

A complication is accounting for dropped packets on the unreliable channel. One option is for clients to ack host updates with their input messages, which the host can use to re-broadcast from a recent mutations buffer, or send a full snapshot if needed. Newly joined clients will always need a full snapshot.

misterwilliam commented 8 years ago

Is decreasing the size of the full snapshot also an option? It seems surprising to me that sending the full snapshot 15 times / sec, yields 300 - 500 kB/sec.

d4l3k commented 8 years ago

The snapshots are highly compressible data. Any considerations to using something like https://github.com/pieroxy/lz-string/ to compress it before sending it over the wire?

aomarks commented 8 years ago

The reason for the large size is that we're sending almost all of the game data in every snapshot. At any time, most objects probably aren't moving (e.g. asteroids), most other attributes change slowly (e.g. hp), and many attributes never change (e.g. collision boxes). This was my quick and dirty way to get things working, but it always seemed clear that only sending deltas would be much better.

Some rough numbers:

now: 40 kB per snapshot (40,000 UTF-8 JSON chars) gzipped: 12 kB delta-only when 10 positions changed: 1 kB delta-only gzipped: 0.5 kB

Another thing to consider is that the current approach requires a lot of new allocations from JSON parsing. The snapshot I looked at had 900 sub-objects. Don't want to make any performance claims since I haven't measured anything (other than seeing a saw-tooth in the chrome memory timeline), but my intuition is that there would be nice savings on GC churn by not re-allocating the entire game state 15 times a second.

So I think switching from snapshots to deltas is a good place to start -- I think it's the most core issue. We can also later try more space efficient serializations than JSON (e.g. FlatBuffers looks interesting because it is zero-alloc) and compression (lz-string looks neat) if the cost/benefit makes sense (I assume JSON parsing is very fast in Chrome, and there's no native compression API).

aomarks commented 8 years ago

I just pushed https://github.com/aomarks/bridgesim/commit/8a77b0f32f9004496d9b25c0f0b1a0529ec70b2d which lowers the baseline data rate to around 1-2 kB/s. There are some remaining bugs/issues I'm working on. A bunch more details in the commit log.