gpui: Small perf optimizations (#40767)

Some random findings based on profiling

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Lukas Wirth 2025-10-23 15:26:27 +02:00 committed by GitHub
parent 4f0a44896a
commit 738e248109
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 78 additions and 88 deletions

View file

@ -34,15 +34,14 @@ where
pub fn insert(&mut self, new_bounds: Bounds<U>) -> u32 {
// If the tree is empty, make the root the new leaf.
if self.root.is_none() {
let Some(mut index) = self.root else {
let new_node = self.push_leaf(new_bounds, 1);
self.root = Some(new_node);
return 1;
}
};
// Search for the best place to add the new leaf based on heuristics.
let mut max_intersecting_ordering = 0;
let mut index = self.root.unwrap();
while let Node::Internal {
left,
right,

View file

@ -572,18 +572,14 @@ impl DispatchTree {
focus_path
}
pub fn view_path(&self, view_id: EntityId) -> SmallVec<[EntityId; 8]> {
let mut view_path: SmallVec<[EntityId; 8]> = SmallVec::new();
pub fn view_path_reversed(&self, view_id: EntityId) -> impl Iterator<Item = EntityId> {
let mut current_node_id = self.view_node_ids.get(&view_id).copied();
while let Some(node_id) = current_node_id {
let node = self.node(node_id);
if let Some(view_id) = node.view_id {
view_path.push(view_id);
}
current_node_id = node.parent;
}
view_path.reverse(); // Reverse the path so it goes from the root to the view node.
view_path
std::iter::successors(
current_node_id.map(|node_id| self.node(node_id)),
|node_id| Some(self.node(node_id.parent?)),
)
.filter_map(|node| node.view_id)
}
pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {

View file

@ -3,7 +3,6 @@ use crate::{
point, size,
};
use collections::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
use stacksafe::{StackSafe, stacksafe};
use std::{fmt::Debug, ops::Range};
use taffy::{
@ -31,6 +30,7 @@ pub struct TaffyLayoutEngine {
taffy: TaffyTree<NodeContext>,
absolute_layout_bounds: FxHashMap<LayoutId, Bounds<Pixels>>,
computed_layouts: FxHashSet<LayoutId>,
layout_bounds_scratch_space: Vec<LayoutId>,
}
const EXPECT_MESSAGE: &str = "we should avoid taffy layout errors by construction if possible";
@ -43,6 +43,7 @@ impl TaffyLayoutEngine {
taffy,
absolute_layout_bounds: FxHashMap::default(),
computed_layouts: FxHashSet::default(),
layout_bounds_scratch_space: Vec::new(),
}
}
@ -168,7 +169,7 @@ impl TaffyLayoutEngine {
//
if !self.computed_layouts.insert(id) {
let mut stack = SmallVec::<[LayoutId; 64]>::new();
let mut stack = &mut self.layout_bounds_scratch_space;
stack.push(id);
while let Some(id) = stack.pop() {
self.absolute_layout_bounds.remove(&id);
@ -177,7 +178,7 @@ impl TaffyLayoutEngine {
.children(id.into())
.expect(EXPECT_MESSAGE)
.into_iter()
.map(Into::into),
.map(LayoutId::from),
);
}
}

View file

@ -1316,9 +1316,7 @@ impl Window {
for view_id in self
.rendered_frame
.dispatch_tree
.view_path(view_id)
.into_iter()
.rev()
.view_path_reversed(view_id)
{
if !self.dirty_views.insert(view_id) {
break;
@ -2277,19 +2275,14 @@ impl Window {
}
self.next_frame.deferred_draws.extend(
self.rendered_frame.deferred_draws
[range.start.deferred_draws_index..range.end.deferred_draws_index]
.iter()
.map(|deferred_draw| DeferredDraw {
current_view: deferred_draw.current_view,
parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
element_id_stack: deferred_draw.element_id_stack.clone(),
text_style_stack: deferred_draw.text_style_stack.clone(),
priority: deferred_draw.priority,
element: None,
absolute_offset: deferred_draw.absolute_offset,
prepaint_range: deferred_draw.prepaint_range.clone(),
paint_range: deferred_draw.paint_range.clone(),
self.rendered_frame
.deferred_draws
.drain(range.start.deferred_draws_index..range.end.deferred_draws_index)
.map(|mut deferred_draw| {
deferred_draw.parent_node =
reused_subtree.refresh_node_id(deferred_draw.parent_node);
deferred_draw.element = None;
deferred_draw
}),
);
}
@ -4902,7 +4895,7 @@ pub enum ElementId {
/// A code location.
CodeLocation(core::panic::Location<'static>),
/// A labeled child of an element.
NamedChild(Box<ElementId>, SharedString),
NamedChild(Arc<ElementId>, SharedString),
}
impl ElementId {
@ -5016,7 +5009,7 @@ impl From<(&'static str, u32)> for ElementId {
impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
fn from((id, name): (ElementId, T)) -> Self {
ElementId::NamedChild(Box::new(id), name.into())
ElementId::NamedChild(Arc::new(id), name.into())
}
}

View file

@ -162,7 +162,7 @@ impl ProjectEnvironment {
.get("PATH")
.map(|path| path.as_str())
.unwrap_or_default();
log::info!(
log::debug!(
"using project environment variables shell launched in {:?}. PATH={:?}",
abs_path,
path

View file

@ -389,11 +389,12 @@ impl Rope {
if offset >= self.summary().len_utf16 {
return self.summary().len;
}
let mut cursor = self.chunks.cursor::<Dimensions<OffsetUtf16, usize>>(());
cursor.seek(&offset, Bias::Left);
let overshoot = offset - cursor.start().0;
cursor.start().1
+ cursor.item().map_or(Default::default(), |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<OffsetUtf16, usize>, _>((), &offset, Bias::Left);
let overshoot = offset - start.0;
start.1
+ item.map_or(Default::default(), |chunk| {
chunk.as_slice().offset_utf16_to_offset(overshoot)
})
}
@ -402,11 +403,12 @@ impl Rope {
if offset >= self.summary().len {
return self.summary().lines;
}
let mut cursor = self.chunks.cursor::<Dimensions<usize, Point>>(());
cursor.seek(&offset, Bias::Left);
let overshoot = offset - cursor.start().0;
cursor.start().1
+ cursor.item().map_or(Point::zero(), |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<usize, Point>, _>((), &offset, Bias::Left);
let overshoot = offset - start.0;
start.1
+ item.map_or(Point::zero(), |chunk| {
chunk.as_slice().offset_to_point(overshoot)
})
}
@ -415,11 +417,12 @@ impl Rope {
if offset >= self.summary().len {
return self.summary().lines_utf16();
}
let mut cursor = self.chunks.cursor::<Dimensions<usize, PointUtf16>>(());
cursor.seek(&offset, Bias::Left);
let overshoot = offset - cursor.start().0;
cursor.start().1
+ cursor.item().map_or(PointUtf16::zero(), |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<usize, PointUtf16>, _>((), &offset, Bias::Left);
let overshoot = offset - start.0;
start.1
+ item.map_or(PointUtf16::zero(), |chunk| {
chunk.as_slice().offset_to_point_utf16(overshoot)
})
}
@ -428,11 +431,12 @@ impl Rope {
if point >= self.summary().lines {
return self.summary().lines_utf16();
}
let mut cursor = self.chunks.cursor::<Dimensions<Point, PointUtf16>>(());
cursor.seek(&point, Bias::Left);
let overshoot = point - cursor.start().0;
cursor.start().1
+ cursor.item().map_or(PointUtf16::zero(), |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<Point, PointUtf16>, _>((), &point, Bias::Left);
let overshoot = point - start.0;
start.1
+ item.map_or(PointUtf16::zero(), |chunk| {
chunk.as_slice().point_to_point_utf16(overshoot)
})
}
@ -441,13 +445,11 @@ impl Rope {
if point >= self.summary().lines {
return self.summary().len;
}
let mut cursor = self.chunks.cursor::<Dimensions<Point, usize>>(());
cursor.seek(&point, Bias::Left);
let overshoot = point - cursor.start().0;
cursor.start().1
+ cursor
.item()
.map_or(0, |chunk| chunk.as_slice().point_to_offset(overshoot))
let (start, _, item) =
self.chunks
.find::<Dimensions<Point, usize>, _>((), &point, Bias::Left);
let overshoot = point - start.0;
start.1 + item.map_or(0, |chunk| chunk.as_slice().point_to_offset(overshoot))
}
pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
@ -462,11 +464,12 @@ impl Rope {
if point >= self.summary().lines_utf16() {
return self.summary().len;
}
let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, usize>>(());
cursor.seek(&point, Bias::Left);
let overshoot = point - cursor.start().0;
cursor.start().1
+ cursor.item().map_or(0, |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<PointUtf16, usize>, _>((), &point, Bias::Left);
let overshoot = point - start.0;
start.1
+ item.map_or(0, |chunk| {
chunk.as_slice().point_utf16_to_offset(overshoot, clip)
})
}
@ -475,11 +478,12 @@ impl Rope {
if point.0 >= self.summary().lines_utf16() {
return self.summary().lines;
}
let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, Point>>(());
cursor.seek(&point.0, Bias::Left);
let overshoot = Unclipped(point.0 - cursor.start().0);
cursor.start().1
+ cursor.item().map_or(Point::zero(), |chunk| {
let (start, _, item) =
self.chunks
.find::<Dimensions<PointUtf16, Point>, _>((), &point.0, Bias::Left);
let overshoot = Unclipped(point.0 - start.0);
start.1
+ item.map_or(Point::zero(), |chunk| {
chunk.as_slice().unclipped_point_utf16_to_point(overshoot)
})
}
@ -492,33 +496,30 @@ impl Rope {
}
pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
let mut cursor = self.chunks.cursor::<OffsetUtf16>(());
cursor.seek(&offset, Bias::Right);
if let Some(chunk) = cursor.item() {
let overshoot = offset - cursor.start();
*cursor.start() + chunk.as_slice().clip_offset_utf16(overshoot, bias)
let (start, _, item) = self.chunks.find::<OffsetUtf16, _>((), &offset, Bias::Right);
if let Some(chunk) = item {
let overshoot = offset - start;
start + chunk.as_slice().clip_offset_utf16(overshoot, bias)
} else {
self.summary().len_utf16
}
}
pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
let mut cursor = self.chunks.cursor::<Point>(());
cursor.seek(&point, Bias::Right);
if let Some(chunk) = cursor.item() {
let overshoot = point - cursor.start();
*cursor.start() + chunk.as_slice().clip_point(overshoot, bias)
let (start, _, item) = self.chunks.find::<Point, _>((), &point, Bias::Right);
if let Some(chunk) = item {
let overshoot = point - start;
start + chunk.as_slice().clip_point(overshoot, bias)
} else {
self.summary().lines
}
}
pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
let mut cursor = self.chunks.cursor::<PointUtf16>(());
cursor.seek(&point.0, Bias::Right);
if let Some(chunk) = cursor.item() {
let overshoot = Unclipped(point.0 - cursor.start());
*cursor.start() + chunk.as_slice().clip_point_utf16(overshoot, bias)
let (start, _, item) = self.chunks.find::<PointUtf16, _>((), &point.0, Bias::Right);
if let Some(chunk) = item {
let overshoot = Unclipped(point.0 - start);
start + chunk.as_slice().clip_point_utf16(overshoot, bias)
} else {
self.summary().lines_utf16()
}