Memory and Rendering Performance
March 12, 2026 ·Version 0.3.4
Fog Panther v0.3.4 ships a set of internal optimizations that dramatically reduce memory consumption and improve rendering performance, particularly for large documents and long editing sessions.
Compressed Undo History
The undo system now stores tile snapshots as zstd-compressed data instead of full uncompressed copies. Every brush stroke, fill, or filter application that previously stored raw 16 KB tile buffers now compresses them at capture time using zstd level 1, which runs at roughly 500 MB/s.
The result: 3x to 10x less memory per undo step, depending on tile content. The fixed 256 MB undo budget that previously held around 80 significant brush strokes now effectively holds 250 to 800. Undo and redo remain instantaneous - decompressing a tile takes approximately 11 microseconds.
The on-disk FOG format already used zstd compression, so saved files are unchanged. Only the in-memory representation is affected.
Display Surface Caching
Non-RGBA8 pixel formats - RGBA16, CMYKA, Grayscale - require a format conversion to produce the Cairo ARGB32 surface used for screen display. Previously, this conversion ran on every visible tile on every frame.
Tiles now cache their display surface after the first conversion. The cache is invalidated automatically whenever the tile data changes. For a 16-bit document with 200 visible tiles, this eliminates 200 format conversions per frame during panning and zooming.
Proactive Tile Cache Trimming
The tile cache previously waited until it exceeded its memory limit before evicting entries, causing brief memory overshoot. It now begins trimming at 90% capacity and trims down to 85%, creating a hysteresis band that prevents repeated eviction on the next insert.
Checkerboard Pattern Caching
The transparency checkerboard pattern - drawn behind every document on every frame - was previously created and destroyed each render pass. It is now created once and reused for the lifetime of the process.
Bug Fixes
This release also includes several correctness fixes discovered during review of the optimization work:
- Display cache is now properly invalidated by all pixel-writing functions, not only the raw data accessor
- History serialization no longer writes a malformed flag byte sequence when a compressed tile decompresses to void
- Redo of erasure operations now correctly restores void tiles
- Tile cache memory accounting is now correct when replacing a cached tile with one of a different pixel format
- Checkerboard pattern initialization is now thread-safe