miniprofiler_ui: Improve MiniProfiler to use uniform list (#43457)
Release Notes: - N/A --- - Apply uniform_list for timing list for performance. - Add paddings for window. - Add space to `ms`, before: `100ms` after `100 ms`. ## Before <img width="1392" height="860" alt="image" src="https://github.com/user-attachments/assets/9706a96f-7093-4d4f-832f-306948a9b17b" /> ## After <img width="1392" height="864" alt="image" src="https://github.com/user-attachments/assets/38df1b71-15e7-4101-b0c9-ecdcdb7752d7" />
This commit is contained in:
@@ -11,7 +11,7 @@ use crate::{
|
||||
StyleRefinement, Styled, Window, point, size,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
||||
use std::{cell::RefCell, cmp, ops::Range, rc::Rc, usize};
|
||||
|
||||
use super::ListHorizontalSizingBehavior;
|
||||
|
||||
@@ -235,6 +235,11 @@ impl UniformListScrollHandle {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Scroll to the bottom of the list.
|
||||
pub fn scroll_to_bottom(&self) {
|
||||
self.scroll_to_item(usize::MAX, ScrollStrategy::Bottom);
|
||||
}
|
||||
}
|
||||
|
||||
impl Styled for UniformList {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
use std::{
|
||||
ops::Range,
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use gpui::{
|
||||
App, AppContext, ClipboardItem, Context, Entity, Hsla, InteractiveElement, IntoElement,
|
||||
ParentElement, Render, ScrollHandle, SerializedTaskTiming, SharedString,
|
||||
StatefulInteractiveElement, Styled, Task, TaskTiming, TitlebarOptions, WindowBounds,
|
||||
WindowHandle, WindowOptions, div, prelude::FluentBuilder, px, relative, size,
|
||||
App, AppContext, ClipboardItem, Context, Div, Entity, Hsla, InteractiveElement,
|
||||
ParentElement as _, Render, SerializedTaskTiming, SharedString, StatefulInteractiveElement,
|
||||
Styled, Task, TaskTiming, TitlebarOptions, UniformListScrollHandle, WindowBounds, WindowHandle,
|
||||
WindowOptions, div, prelude::FluentBuilder, px, relative, size, uniform_list,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{
|
||||
Workspace,
|
||||
ui::{
|
||||
ActiveTheme, Button, ButtonCommon, ButtonStyle, Checkbox, Clickable, ToggleState, Tooltip,
|
||||
WithScrollbar, h_flex, v_flex,
|
||||
ActiveTheme, Button, ButtonCommon, ButtonStyle, Checkbox, Clickable, Divider,
|
||||
ScrollableHandle as _, ToggleState, Tooltip, WithScrollbar, h_flex, v_flex,
|
||||
},
|
||||
};
|
||||
use zed_actions::OpenPerformanceProfiler;
|
||||
@@ -95,7 +96,7 @@ pub struct ProfilerWindow {
|
||||
data: DataMode,
|
||||
include_self_timings: ToggleState,
|
||||
autoscroll: bool,
|
||||
scroll_handle: ScrollHandle,
|
||||
scroll_handle: UniformListScrollHandle,
|
||||
workspace: Option<WindowHandle<Workspace>>,
|
||||
_refresh: Option<Task<()>>,
|
||||
}
|
||||
@@ -111,7 +112,7 @@ impl ProfilerWindow {
|
||||
data: DataMode::Realtime(None),
|
||||
include_self_timings: ToggleState::Unselected,
|
||||
autoscroll: true,
|
||||
scroll_handle: ScrollHandle::new(),
|
||||
scroll_handle: UniformListScrollHandle::default(),
|
||||
workspace: workspace_handle,
|
||||
_refresh: Some(Self::begin_listen(cx)),
|
||||
});
|
||||
@@ -128,16 +129,7 @@ impl ProfilerWindow {
|
||||
.get_current_thread_timings();
|
||||
|
||||
this.update(cx, |this: &mut ProfilerWindow, cx| {
|
||||
let scroll_offset = this.scroll_handle.offset();
|
||||
let max_offset = this.scroll_handle.max_offset();
|
||||
this.autoscroll = -scroll_offset.y >= (max_offset.height - px(5.0));
|
||||
|
||||
this.data = DataMode::Realtime(Some(data));
|
||||
|
||||
if this.autoscroll {
|
||||
this.scroll_handle.scroll_to_bottom();
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
@@ -157,12 +149,7 @@ impl ProfilerWindow {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_timing(
|
||||
&self,
|
||||
value_range: Range<Instant>,
|
||||
item: TimingBar,
|
||||
cx: &App,
|
||||
) -> impl IntoElement {
|
||||
fn render_timing(value_range: Range<Instant>, item: TimingBar, cx: &App) -> Div {
|
||||
let time_ms = item.end.duration_since(item.start).as_secs_f32() * 1000f32;
|
||||
|
||||
let remap = value_range
|
||||
@@ -227,10 +214,10 @@ impl ProfilerWindow {
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.min_w(px(60.0))
|
||||
.min_w(px(70.))
|
||||
.flex_shrink_0()
|
||||
.text_right()
|
||||
.child(format!("{:.1}ms", time_ms)),
|
||||
.child(format!("{:.1} ms", time_ms)),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -241,15 +228,23 @@ impl Render for ProfilerWindow {
|
||||
window: &mut gpui::Window,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
let scroll_offset = self.scroll_handle.offset();
|
||||
let max_offset = self.scroll_handle.max_offset();
|
||||
self.autoscroll = -scroll_offset.y >= (max_offset.height - px(24.));
|
||||
if self.autoscroll {
|
||||
self.scroll_handle.scroll_to_bottom();
|
||||
}
|
||||
|
||||
v_flex()
|
||||
.id("profiler")
|
||||
.w_full()
|
||||
.h_full()
|
||||
.gap_2()
|
||||
.bg(cx.theme().colors().surface_background)
|
||||
.text_color(cx.theme().colors().text)
|
||||
.child(
|
||||
h_flex()
|
||||
.py_2()
|
||||
.px_4()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(
|
||||
@@ -346,53 +341,70 @@ impl Render for ProfilerWindow {
|
||||
|
||||
let min = e[0].start;
|
||||
let max = e[e.len() - 1].end.unwrap_or_else(|| Instant::now());
|
||||
div.child(
|
||||
let timings = Rc::new(
|
||||
e.into_iter()
|
||||
.filter(|timing| {
|
||||
timing
|
||||
.end
|
||||
.unwrap_or_else(|| Instant::now())
|
||||
.duration_since(timing.start)
|
||||
.as_millis()
|
||||
>= 1
|
||||
})
|
||||
.filter(|timing| {
|
||||
if self.include_self_timings.selected() {
|
||||
true
|
||||
} else {
|
||||
!timing.location.file().ends_with("miniprofiler_ui.rs")
|
||||
}
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
div.child(Divider::horizontal()).child(
|
||||
v_flex()
|
||||
.id("timings.bars")
|
||||
.overflow_scroll()
|
||||
.w_full()
|
||||
.h_full()
|
||||
.gap_2()
|
||||
.track_scroll(&self.scroll_handle)
|
||||
.on_scroll_wheel(cx.listener(|this, _, _, _cx| {
|
||||
let scroll_offset = this.scroll_handle.offset();
|
||||
let max_offset = this.scroll_handle.max_offset();
|
||||
this.autoscroll = -scroll_offset.y >= (max_offset.height - px(5.0));
|
||||
}))
|
||||
.children(
|
||||
e.iter()
|
||||
.filter(|timing| {
|
||||
timing
|
||||
.end
|
||||
.unwrap_or_else(|| Instant::now())
|
||||
.duration_since(timing.start)
|
||||
.as_millis()
|
||||
>= 1
|
||||
})
|
||||
.filter(|timing| {
|
||||
if self.include_self_timings.selected() {
|
||||
true
|
||||
} else {
|
||||
!timing.location.file().ends_with("miniprofiler_ui.rs")
|
||||
.child(
|
||||
uniform_list("list", timings.len(), {
|
||||
let timings = timings.clone();
|
||||
move |visible_range, _, cx| {
|
||||
let mut items = vec![];
|
||||
for i in visible_range {
|
||||
let timing = &timings[i];
|
||||
let value_range =
|
||||
max.checked_sub(Duration::from_secs(10)).unwrap_or(min)
|
||||
..max;
|
||||
items.push(Self::render_timing(
|
||||
value_range,
|
||||
TimingBar {
|
||||
location: timing.location,
|
||||
start: timing.start,
|
||||
end: timing.end.unwrap_or_else(|| Instant::now()),
|
||||
color: cx
|
||||
.theme()
|
||||
.accents()
|
||||
.color_for_index(i as u32),
|
||||
},
|
||||
cx,
|
||||
));
|
||||
}
|
||||
})
|
||||
.enumerate()
|
||||
.map(|(i, timing)| {
|
||||
self.render_timing(
|
||||
max.checked_sub(Duration::from_secs(10)).unwrap_or(min)
|
||||
..max,
|
||||
TimingBar {
|
||||
location: timing.location,
|
||||
start: timing.start,
|
||||
end: timing.end.unwrap_or_else(|| Instant::now()),
|
||||
color: cx.theme().accents().color_for_index(i as u32),
|
||||
},
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
),
|
||||
items
|
||||
}
|
||||
})
|
||||
.p_4()
|
||||
.on_scroll_wheel(cx.listener(|this, _, _, cx| {
|
||||
this.autoscroll = false;
|
||||
cx.notify();
|
||||
}))
|
||||
.track_scroll(self.scroll_handle.clone())
|
||||
.size_full(),
|
||||
)
|
||||
.vertical_scrollbar_for(self.scroll_handle.clone(), window, cx),
|
||||
)
|
||||
.vertical_scrollbar_for(self.scroll_handle.clone(), window, cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user