Level File Format Improvements #79
Labels
No Milestone
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: SketchyMaze/doodle#79
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The level file format has room for improvement (better compression), currently they are JSON files compressed with gzip and all chunks use the MapAccessor (only chunker implemented) which maps points to palette indexes.
Ideas for improvements:
Add Limits
To get smaller integers/less waste in memory:
Coordinates inside a chunk can therefore be uint8's.Currently: render.Point (X, Y int) are used everywhere, it's 64-bit numbers, this is OK for level coordinates but for in-chunk coordinates moving to uint8's can be an 8X reduction in size.
Chunkers
Improve: MapAccessor
It's a
map[render.Point]*Swatch
type and in JSON format it becomes a dictionary where keys are X,Y coords like "123,100" and values are integers for palette index. All these numbers are 64-bits in memory so when loaded as Go structs it's at least 24 bytes of memory per pixel.Possibly can improve the MarshalJSON implementation for better compression. For backwards compatibility, UnmarshalJSON loads into a
map[string]int
and it could do two passes when decoding a level: unmarshal the new format (not amap[string]int
) and if the legacy level doesn't fit that format (returns an error) then load it the old way, but on next re-save, the Marshal function will use the new encoding.New encoding could possibly be: stream of uint8 bytes, {X, Y, index}, can be a []byte type in Go that automagically encodes as base64 in JSON. Size savings could be:
"100,120": "10"
9 bytes in digits, 15 with json symbols0x64 0x78 0x0a
3 bytes hex per pixel.Done: MapAccessors now serialize to binary using triplets of {varint X, varint Y, uvarint Palette}.
Add: GridAccessor
Planned since the beginning but not added yet, it would be a 2D array for densely packed chunks. Palette index 255 (0xFF) can be the null value since palettes currently index from 0 upwards.
When serializing to JSON use a run-length encoding for higher compression.
Add: UniformAccessor
When a whole entire chunk is filled all in the same color, we could save a LOT of space by having this chunker just treat all of its pixels as the same: Get(x,y) returns the color always. On Set() if the uniformity is going to be broken, switch to a GridAccessor.
Load Rebalance
On level save, the level can choose a new accessor per chunk based on how dense it is (exact balance to be tuned), e.g.
Runtime Performance