# Performance Analysis Measurements with the `--perf` flag on `desktop.glbc`. ## Measurement Results **Steady state** (no events, idle): ``` VDOM: 6.6ms | Style: 0.3ms | Render: 7.2ms | Total: 14.1ms ``` **Under events** (slider drag, peak values): ``` VDOM: 17.4ms | Style: 0.8ms | Render: 15.2ms | Total: 33.5ms ⚠️ ``` **60 FPS frame budget: 16ms.** At idle we fit (14ms), under events — not (up to 33ms). ## Bottleneck Analysis ### Style matching — NOT a bottleneck (0.3-0.8ms) Style matching takes less than 1ms even at peak. This is the result of: - **Phase 4** (StyleIndex) — O(K) instead of O(N×M) - **Phase 8** (StyleCache) — computed style memoization ### VDOM eval — main consumer (6-17ms) At idle ~6.6ms — a full traversal of the Element tree. Under events up to 17ms: - `evaluate_vdom_incr` recalculates dirty elements (Phase 3) - Each event can dirty entire subtrees - Internally: `resolve_string`, `resolve_prop`, `compute_cached`, recursive traversal ### Render — second consumer (7-15ms) **This is where the main optimization headroom lies.** `render_element` creates ALL Iced widgets from scratch every frame, even if the Element hasn't changed. Iced then diffs the new tree against the old one — but the tree construction itself costs ~7ms. ### Scenario: slider 1. `SliderChanged` → `age` and `volume_level` change 2. `tracker.on_variable_changed` → dirty_set for dependent elements 3. `evaluate_vdom_incr` recalculates dirty elements and their children 4. `view()` → `render_element` for ALL elements (full re-render) 5. Result: VDOM 13ms + Render 14ms = 27ms — frame drop The first few frames after an event are the heaviest (VDOM ~13ms), then stabilize (~7ms) as dirty_set gradually clears. ## Recommendations 1. **Phase 9.3 — widget cache** — would reduce Render from 7ms to ~0ms for unchanged elements. If 1 out of 50 elements changes, only that one needs re-rendering. This would lower total time from 14ms to ~7ms at idle. 2. **Phase 1 — Value enum in styles** — `ComputedStyle::compute()` and `parse_*()` take `&str` and parse each property. Passing `&Value` instead would skip parsing. Potentially speeds up both style matching and VDOM eval. 3. **Phase 2 — InternedStr** — string comparisons (`type_name == "Button"`, `key == "padding-top"`) happen thousands of times per frame. Replacing with u32 comparison would give 1.5-2× in VDOM and render paths. 4. **Phase 0.3 — flamegraph** — confirm hypotheses with profiler measurements (`perf record`) before investing in optimization.