Skip to content

Performance

Fleury reduces rebuilds, virtualizes large datasets, and emits only changed cells. A row selection should not rebuild a hundred-thousand rows, and an idle app should not write bytes. A visual frame still paints a complete back buffer and compares it with the previous frame; culling and repaint caches reduce the work inside that paint pass.

This page describes those boundaries and the benchmarks that check them.

Fleury’s performance model has five practical goals:

PromiseWhat should happen
Build and layout work are retainedsetState queues dirty elements; clean builds and unchanged layout can be reused. Painting starts at the root, with culling and explicit repaint caches.
Output is damage-basedThe terminal target writes changed cells as ANSI. The browser target applies changed cell ranges or DOM patches.
Large data is virtualizedTables, trees, and lists bind the visible window instead of rebuilding the full dataset.
Streaming work stays scopedLogs and subprocess output append incrementally. Markdown reuses complete parsed lines and reparses the appended tail; source replacements or parser-option changes rebuild the parse.
Idle is quietIf nothing changed, Fleury should schedule no meaningful work and emit no frame output.

Those promises come from the same architecture described in Overview and Architecture deep dive: a retained widget/element/render/semantics pipeline that paints into a cell grid, then hands changed cells to the active target.

The benchmark suite is organized around the places terminal apps usually get expensive:

ConcernWhat it tells us
Startup and first paintHow much runtime overhead every app pays before the UI gets interesting.
Input latencyWhether text fields, paste, cursor movement, completions, and command entry stay responsive.
Large data navigationWhether tables and trees stay tied to the virtualized visible window instead of dataset size.
Streaming textWhether log, subprocess, and Markdown appends stay within their workload budgets, including parsing, layout, paint, and output.
Update cadenceWhether many independent widgets can tick without broad redraws.
Layout and resize churnWhether Fleury recomputes only affected layout regions and recovers cleanly from terminal resizes.
App-shell churnWhether overlays, command palettes, focus restoration, and transient UI creation stay cheap.
Wire and process costHow many bytes, frames, CPU, and RSS a real terminal run consumes.

The full scenario matrix and peer target rationale live in the benchmark index.

The same discipline carries to the MCP agent surface. Reads are bounded: get_ui and action results are node-capped and token-trimmed. Id-to-node lookup uses a cached index for each tree revision, and wait_for_change caps settling so an animating app can return without running to its timeout. Legacy clients (MCP 2025-06-18 and earlier) can subscribe to compact tree deltas; current clients use revision-based wait_for_change because Fleury does not yet advertise modern MCP streaming subscriptions.

The June 29, 2026 baseline measured a delta at about 0.3% of a full re-read, indexed lookup at about 477× faster than a tree walk, and capped settling at about 3.7× faster than uncapped settling on its 80-row, 332-node dashboard fixture. Those are recorded measurements, not guarantees for every app. CI enforces the baseline’s stated thresholds, which allow timing variance and do not require reproducing those exact speedups: a delta under 2% of a full re-read, capped settling more than 1.5× faster than uncapped, and indexed lookup more than 2× faster than a tree walk.

From a Fleury framework checkout:

Terminal window
fleury benchmark list
fleury benchmark local SB.6 --warmup=1 --iterations=3 --json
fleury benchmark profile SB.6 --warmup=1 --iterations=5
fleury benchmark wire sb6 --runs=3
fleury benchmark manifest --json

Use local runs to inspect Fleury’s own frame, CPU, and memory behavior. Use profile when a scenario needs VM service CPU or allocation detail. Use wire runs when the question includes the terminal boundary: bytes written, frames emitted, time to first byte, CPU, RSS, and peer fixtures under a real PTY.

Benchmark output should make the next engineering question clearer. Local and profile runs show whether Fleury’s own pipeline is staying proportional to the change; wire runs, what happens at the terminal boundary; peer fixture runs, how the same scenario behaves when expressed with other frameworks’ natural APIs.

For durable comparisons, keep the fixture shape, terminal, machine, framework versions, and repeated-run variance beside the result. That context makes the captures useful for regression review, fixture-shape review, runtime-floor analysis, and follow-up profiling.

The checked-in evidence supports a narrower claim than “fastest TUI framework”: Fleury keeps interactive work responsive and is competitive on many matched terminal-wire workloads. Native peers retain an inherent startup and RSS floor advantage, and a public cross-framework ranking requires fresh peer versions, bare-metal repeated runs, and equivalent fixture shapes.