Skip to content

Commit 8fe09a0

Browse files
matej21claude
andcommitted
perf: cache entity views to skip layout recomputation on non-dirty frames
GPUI rebuilds and re-lays-out the entire taffy tree on every frame, even for views that haven't changed. Use AnyView::cached(style) on Entity children so non-dirty views are represented as a single taffy leaf node and their previous layout+paint is reused from the prior frame. Cached views: SimpleRoot→RootView, RootView→Sidebar/ProjectColumn, ProjectColumn→LayoutContainer, LayoutContainer→TerminalPane/children, TerminalPane→TerminalContent, DetachedTerminal→TerminalContent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 25d8568 commit 8fe09a0

File tree

7 files changed

+30
-12
lines changed

7 files changed

+30
-12
lines changed

crates/okena-views-terminal/src/layout/layout_container.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,9 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
246246
.flex_1()
247247
.min_h_0()
248248
.relative()
249-
.child(self.terminal_pane.clone().unwrap())
249+
.child(AnyView::from(self.terminal_pane.clone().unwrap()).cached(
250+
StyleRefinement::default().size_full()
251+
))
250252
.child(self.render_drop_zones(terminal_id, cx, &self.active_drag.clone())),
251253
)
252254
}
@@ -395,7 +397,9 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
395397
.size_full()
396398
.min_h_0()
397399
.min_w_0()
398-
.child(container);
400+
.child(AnyView::from(container).cached(
401+
StyleRefinement::default().size_full()
402+
));
399403
}
400404

401405
let is_horizontal = direction == SplitDirection::Horizontal;
@@ -474,7 +478,9 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
474478
.flex_basis(relative(size_percent / 100.0))
475479
.min_w_0()
476480
.min_h_0()
477-
.child(container)
481+
.child(AnyView::from(container).cached(
482+
StyleRefinement::default().size_full()
483+
))
478484
.into_any_element();
479485

480486
elements.push(child_element);

crates/okena-views-terminal/src/layout/tabs/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
251251

252252
return v_flex()
253253
.size_full()
254-
.child(container);
254+
.child(AnyView::from(container).cached(
255+
StyleRefinement::default().size_full()
256+
));
255257
}
256258

257259
let num_children = children.len();
@@ -303,7 +305,7 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
303305
})
304306
.clone();
305307

306-
container
308+
AnyView::from(container).cached(StyleRefinement::default().size_full())
307309
}),
308310
)
309311
}

crates/okena-views-terminal/src/layout/terminal_pane/render.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ impl<D: ActionDispatch + Send + Sync> Render for TerminalPane<D> {
189189
.min_w_0()
190190
.overflow_hidden()
191191
.relative()
192-
.child(self.content.clone())
192+
.child(AnyView::from(self.content.clone()).cached(
193+
StyleRefinement::default().size_full()
194+
))
193195
.when(show_border, |el| {
194196
el.child(div().absolute().inset_0().border_1().border_color(border_color))
195197
}),

crates/okena-views-terminal/src/overlays/detached_terminal.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,9 @@ impl Render for DetachedTerminalView {
314314
div()
315315
.flex_1()
316316
.min_h_0()
317-
.child(self.content.clone()),
317+
.child(AnyView::from(self.content.clone()).cached(
318+
StyleRefinement::default().size_full()
319+
)),
318320
)
319321
.id("detached-terminal-main")
320322
.on_click(cx.listener(|this, _, window, cx| {

src/simple_root.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use gpui::{
55
AnyView, Bounds, Context, CursorStyle, Decorations, DispatchPhase, Hitbox, HitboxBehavior,
66
InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement, Pixels, Point,
7-
Render, ResizeEdge, Size, Styled, Window, canvas, div, point, prelude::FluentBuilder, px,
7+
Render, ResizeEdge, Size, StyleRefinement, Styled, Window, canvas, div, point, prelude::FluentBuilder, px,
88
};
99

1010
/// Edge detection zone size (pixels) for CSD resize handles.
@@ -94,7 +94,7 @@ impl Render for SimpleRoot {
9494
.absolute(),
9595
)
9696
})
97-
.child(self.view.clone())
97+
.child(self.view.clone().cached(StyleRefinement::default().size_full()))
9898
}
9999
}
100100

src/views/panels/project_column.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,9 @@ impl Render for ProjectColumn {
704704
.flex_1()
705705
.min_h_0()
706706
.overflow_hidden()
707-
.child(self.layout_container.clone().unwrap())
707+
.child(AnyView::from(self.layout_container.clone().unwrap()).cached(
708+
StyleRefinement::default().size_full()
709+
))
708710
.into_any_element()
709711
} else if is_creating {
710712
self.render_creating_state(cx).into_any_element()

src/views/root/render.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ impl RootView {
181181
.w(px(pixel_width))
182182
.flex_shrink_0()
183183
.h_full()
184-
.child(col)
184+
.child(AnyView::from(col).cached(
185+
StyleRefinement::default().size_full()
186+
))
185187
.into_any_element();
186188

187189
elements.push(col_element);
@@ -832,7 +834,9 @@ impl Render for RootView {
832834
div()
833835
.w(px(configured_width))
834836
.h_full()
835-
.child(self.sidebar.clone())
837+
.child(AnyView::from(self.sidebar.clone()).cached(
838+
StyleRefinement::default().size_full()
839+
))
836840
)
837841
})
838842
}

0 commit comments

Comments
 (0)