Performance
Measured, benchmarked, and pinned by tests — not promised.
lotusui is immediate-mode: the frame loop is the hot path, so the library treats it the way low-latency systems treat theirs — no allocations on read-mostly paths, preallocated scratch buffers, virtualization for anything that grows with data, and benchmarks in the test suite so none of it can regress silently. Idle UI costs zero frames: every animation stops requesting invalidation the moment it settles.
Virtualization: 270× on long lists
The one cliff an immediate-mode UI can fall off is laying out everything, every
frame. ListView exists so collections never do: 10,000 rows cost a screenful of
layout per frame.
One frame, 10,000 rows each — 105 vs 10,108 allocations.
The disciplines
Four rules keep every component on budget. Resolve at construction,
not per frame: theming, schemes and scales are plain values fixed in
NewTheme — a custom look compiles to the same instructions as the default.
Cache what's expensive: SVGs rasterize once per name+size+tint and are then a
lock-free map read; text shaping warms up in two phases so the first frame never waits on font
enumeration. Never re-lay-out what can be replayed: animations record a frame
once and translate the recorded ops — moving content can't reflow, and its cost is a copy, not
a layout. Stop when settled: the shared animation clock requests the next
frame only while a value is still moving.
Reproduce it
The numbers above are from the library's own benchmark suite (Go 1.26, macOS,
Intel — expect better on Apple Silicon). TestSVGIconCacheZeroAlloc and the hostile-
constraints layout test run with the ordinary test suite, so the performance contract is checked
on every go test.
go test -bench . -benchmem github.com/ikaito-com/lotusui
BenchmarkSVGIconCacheHit 41.26 ns/op 0 B/op 0 allocs/op
BenchmarkButtonFrame 15 µs/op 14389 B/op 105 allocs/op
BenchmarkListView10k 61 µs/op 14302 B/op 105 allocs/op
BenchmarkScrollable10k 16534 µs/op 2363234 B/op 10108 allocs/op