The server sent the whole army on every snapshot and the client re-cloned
the whole icon layer whenever a unit moved, so a settled world with a
standing army drained the broadcast loop and the frame loop alike.
- Ship only the units and city list that changed, keyed by a per-peer
fingerprint and a serialised hash, and merge those deltas on the client.
- Memoise the battlefield scan on a battle version bumped when a unit
joins, leaves or changes side.
- Skip the DOM writes for units whose snapshot object is unchanged, and
cache the unit-view inner nodes.
- Fold units, cities and tile markers onto the nearest world copy instead
of mirroring the icon layers, which re-cloned thousands of views every
frame; the small decoration layers still mirror, and only on a change.
Frame work at full zoom-out with units moving fell from ~190ms to ~6.5ms.