Tilemap Town takes a short, but noticeable amount of time to load on the 3DS, which is a combination of me not implementing websocket compression yet (because wslay doesn't do it for you and it's not trivial to add, and I couldn't find examples of people doing it), and the 3DS's download speeds just being slow.

So there's this nagging feeling that I should try and have a look at formatting the data differently to see if I can improve the bandwidth usage here, using the current state of the main map as an example of some complicated and realistic test data.

Here's what I got:

Original
   uncompressed:  150155 - 100.00%
   zlib level 6:   18561 - 12.36%
   zlib level 9:   18745 - 12.48%
RLE [[x, y, type, count], ...]
   uncompressed:   84794 - 56.47%
   zlib level 6:   13667 - 9.10%
   zlib level 9:   13247 - 8.82%
RLE [[x, y, type, count], ...] Packed
   uncompressed:   80339 - 53.50%
   zlib level 6:   14520 - 9.67%
   zlib level 9:   14005 - 9.33%
RLE [type, x, y, count, ...]
   uncompressed:  109284 - 72.78%
   zlib level 6:   18860 - 12.56%
   zlib level 9:   18555 - 12.36%
Coordinate list
   uncompressed:   55088 - 36.69%
   zlib level 6:   15250 - 10.16%
   zlib level 9:   15223 - 10.14%
Coordinate list + Counts
   uncompressed:   54681 - 36.42%
   zlib level 6:   13101 - 8.72%
   zlib level 9:   13061 - 8.70%
Coordinate list + Counts + Packing
   uncompressed:   40417 - 26.92%
   zlib level 6:   13199 - 8.79%
   zlib level 9:   13088 - 8.72%

Turns out that some very simple run-length encoding stuff cuts the map size a lot as expected, but Deflate was already handling that redundancy pretty well (if the client supports websocket compression).

By packing I meant I'm packing the bits together into one number, so it's something like 0xRRYYXX where R is the repeat count minus one, instead of a separate X, Y and repeat count. This made the compressed size actually worse.

Switching it over to just having the name/data for each tile once and then listing every place the tile is used helps a lot, but I think it makes the map much more expensive to encode (because it would have to keep a directory of what types are already used, which is difficult when types can be arbitrary JSON objects) while not shrinking the compressed size enough to be worth it.

I think the takeaway is to either leave it how it is or go for the first kind of RLE I tried, which has a small but nonzero impact to how complicated map decoding in clients has to be. It's nice to avoid a breaking protocol change where I don't need to do one, and also nice that the simple format I established years ago actually works fine.

Previous Post Next Post