From 9273054b2b9591ddaebd63c910fe28616b4f7f7d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 6 May 2021 18:44:31 +0200 Subject: [PATCH] Profiler: Show one timeline per process :^) Instead of smashing together all the samples into a single timeline, make one per process and put them all in a ScrollableContainerWidget. This makes it much easier to see which processes were active and when. No timeline is displayed for processes with zero samples in the profile. --- .../Profiler/ProfileTimelineWidget.cpp | 15 ++++++++++++-- .../DevTools/Profiler/ProfileTimelineWidget.h | 4 +++- Userland/DevTools/Profiler/main.cpp | 20 ++++++++++++++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Userland/DevTools/Profiler/ProfileTimelineWidget.cpp b/Userland/DevTools/Profiler/ProfileTimelineWidget.cpp index 748f7e197a..80493aa550 100644 --- a/Userland/DevTools/Profiler/ProfileTimelineWidget.cpp +++ b/Userland/DevTools/Profiler/ProfileTimelineWidget.cpp @@ -8,14 +8,17 @@ #include "Profile.h" #include #include +#include namespace Profiler { -ProfileTimelineWidget::ProfileTimelineWidget(Profile& profile) +ProfileTimelineWidget::ProfileTimelineWidget(Profile& profile, Process const& process) : m_profile(profile) + , m_process(process) { set_fill_with_background_color(true); - set_fixed_height(80); + set_fixed_height(40); + set_fixed_width(m_profile.length_in_ms() / 10); m_hover_time = m_profile.first_timestamp(); } @@ -41,6 +44,12 @@ void ProfileTimelineWidget::paint_event(GUI::PaintEvent& event) float frame_height = (float)frame_inner_rect().height() / (float)m_profile.deepest_stack_depth(); for (auto& event : m_profile.events()) { + if (event.pid != m_process.pid) + continue; + + if (!m_process.valid_at(event.timestamp)) + continue; + u64 t = clamp_timestamp(event.timestamp) - start_of_trace; int x = (int)((float)t * column_width); int cw = max(1, (int)column_width); @@ -66,6 +75,8 @@ void ProfileTimelineWidget::paint_event(GUI::PaintEvent& event) { StringBuilder timeline_desc_builder; + timeline_desc_builder.appendff("{} ({}), ", m_process.executable, m_process.pid); + timeline_desc_builder.appendff("Time: {} ms", normalized_hover_time - start_of_trace); if (normalized_start_time != normalized_end_time) { auto start = normalized_start_time - start_of_trace; diff --git a/Userland/DevTools/Profiler/ProfileTimelineWidget.h b/Userland/DevTools/Profiler/ProfileTimelineWidget.h index 66dfebaec1..76624aa955 100644 --- a/Userland/DevTools/Profiler/ProfileTimelineWidget.h +++ b/Userland/DevTools/Profiler/ProfileTimelineWidget.h @@ -10,6 +10,7 @@ namespace Profiler { +class Process; class Profile; class ProfileTimelineWidget final : public GUI::Frame { @@ -23,11 +24,12 @@ private: virtual void mousemove_event(GUI::MouseEvent&) override; virtual void mouseup_event(GUI::MouseEvent&) override; - explicit ProfileTimelineWidget(Profile&); + explicit ProfileTimelineWidget(Profile&, Process const&); u64 timestamp_at_x(int x) const; Profile& m_profile; + Process const& m_process; bool m_selecting { false }; u64 m_select_start_time { 0 }; diff --git a/Userland/DevTools/Profiler/main.cpp b/Userland/DevTools/Profiler/main.cpp index 56a14d26a0..da2d39c124 100644 --- a/Userland/DevTools/Profiler/main.cpp +++ b/Userland/DevTools/Profiler/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -88,7 +89,24 @@ int main(int argc, char** argv) main_widget.set_fill_with_background_color(true); main_widget.set_layout(); - main_widget.add(*profile); + auto timelines_widget = GUI::Widget::construct(); + timelines_widget->set_layout(); + timelines_widget->set_shrink_to_fit(true); + + for (auto& process : profile->processes()) { + size_t event_count = 0; + for (auto& event : profile->events()) { + if (event.pid == process.pid && process.valid_at(event.timestamp)) + ++event_count; + } + if (!event_count) + continue; + timelines_widget->add(*profile, process); + } + + auto& scrollable_container = main_widget.add(); + scrollable_container.set_widget(timelines_widget.ptr()); + main_widget.add(*profile); auto& tab_widget = main_widget.add();