docs: deep dive into GPUI dirty propagation, SharedBlink, hierarchy flattening results
This commit is contained in:
parent
6f0f276400
commit
54e68df295
1 changed files with 55 additions and 0 deletions
|
|
@ -26,6 +26,61 @@ Key mechanisms:
|
|||
3. **`mark_view_dirty()` walks ancestors** — this is GPUI's fundamental constraint
|
||||
4. **`refreshing=true` on cache miss** cascades down → children can't cache if parent is dirty
|
||||
|
||||
## DEEP DIVE: Why 3% is the floor for div-based views (2026-03-19 late)
|
||||
|
||||
### The full dirty propagation chain (confirmed by source analysis)
|
||||
|
||||
```
|
||||
cx.notify(entity_id)
|
||||
→ App::notify → WindowInvalidator::invalidate_view(entity_id)
|
||||
→ dirty_views.insert(entity_id)
|
||||
→ draw() → invalidate_entities() → mark_view_dirty(entity_id)
|
||||
→ dispatch_tree.view_path_reversed(entity_id) → walks parent chain
|
||||
→ inserts entity + ALL render-time ancestors into dirty_views
|
||||
→ AnyView::prepaint checks: dirty_views.contains(MY entity_id)
|
||||
→ if true: cache MISS, re-render
|
||||
→ if false: cache HIT, replay GPU commands
|
||||
```
|
||||
|
||||
### Why Zed achieves <1% with the SAME mechanism
|
||||
|
||||
Zed's BlinkManager → observer → cx.notify(Editor) → Editor + Pane + Workspace ALL in dirty_views.
|
||||
ALL re-render. But:
|
||||
- Workspace::render() = ~5 div builders = <0.1ms
|
||||
- Pane::render() = ~10 div builders = <0.2ms
|
||||
- Editor::render() = returns EditorElement struct = <0.01ms
|
||||
- EditorElement::prepaint/paint = real work, bounded to visible rows
|
||||
|
||||
Total: <1ms per blink frame. Our ProjectBox::render() = ~9 divs + 3 tab buttons = ~15ms.
|
||||
The 15ms includes Taffy layout + element prepaint + paint pipeline overhead per div.
|
||||
|
||||
### SharedBlink pattern (Arc<AtomicBool>)
|
||||
|
||||
Replaced Entity<BlinkState> with `Arc<AtomicBool>`:
|
||||
- Background timer toggles atomic bool every 500ms
|
||||
- Timer calls cx.notify() on ProjectBox directly (no intermediate entity)
|
||||
- ProjectBox::render() reads bool atomically — no Entity subscription overhead
|
||||
- Same 3% CPU — confirms cost is in render() itself, not entity machinery
|
||||
|
||||
### Hierarchy flattening (4 levels → 2 levels)
|
||||
|
||||
Removed ProjectGrid entity level. ProjectBoxes render directly from Workspace.
|
||||
Dispatch tree: Workspace → ProjectBox (2 levels, same as Zed's Workspace → Pane).
|
||||
CPU unchanged at 3% — confirms cost is per-frame render(), not ancestor walk count.
|
||||
|
||||
### Path to <1%: Custom Element for ProjectBox header
|
||||
|
||||
Convert header (accent stripe + dot + name + CWD + tab bar) from div tree to
|
||||
custom `impl Element` that paints directly via `window.paint_quad()` +
|
||||
`window.text_system().shape_line().paint()`. This eliminates:
|
||||
- 9 div() constructor calls
|
||||
- 9 Taffy layout nodes
|
||||
- 9 prepaint traversals
|
||||
- 9 paint traversals
|
||||
|
||||
Replaced by ~6 direct GPU primitive insertions (paint_quad × 4 + shape_line × 2).
|
||||
Expected reduction: 15ms → <1ms per frame.
|
||||
|
||||
## Overview
|
||||
|
||||
GPUI is the GPU-accelerated UI framework powering the Zed editor. Apache-2.0 licensed (the crate itself; Zed app is GPL-3.0). Pre-1.0 with breaking changes every 2-3 months. 76.7k stars (Zed repo), $32M Sequoia funding.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue