diff options
author | Andreas Kling <kling@serenityos.org> | 2021-05-06 18:44:31 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-06 22:18:45 +0200 |
commit | 9273054b2b9591ddaebd63c910fe28616b4f7f7d (patch) | |
tree | f1beb7ad88880453854718690fe1d507bae1c2b5 | |
parent | 017da44ac2afb084d95f28645d956dbcc79ca214 (diff) | |
download | serenity-9273054b2b9591ddaebd63c910fe28616b4f7f7d.zip |
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.
-rw-r--r-- | Userland/DevTools/Profiler/ProfileTimelineWidget.cpp | 15 | ||||
-rw-r--r-- | Userland/DevTools/Profiler/ProfileTimelineWidget.h | 4 | ||||
-rw-r--r-- | 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 <LibGUI/Painter.h> #include <LibGfx/Font.h> +#include <LibGfx/Palette.h> 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 <LibGUI/MessageBox.h> #include <LibGUI/Model.h> #include <LibGUI/ProcessChooser.h> +#include <LibGUI/ScrollableContainerWidget.h> #include <LibGUI/Splitter.h> #include <LibGUI/TabWidget.h> #include <LibGUI/TableView.h> @@ -88,7 +89,24 @@ int main(int argc, char** argv) main_widget.set_fill_with_background_color(true); main_widget.set_layout<GUI::VerticalBoxLayout>(); - main_widget.add<ProfileTimelineWidget>(*profile); + auto timelines_widget = GUI::Widget::construct(); + timelines_widget->set_layout<GUI::VerticalBoxLayout>(); + 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<ProfileTimelineWidget>(*profile, process); + } + + auto& scrollable_container = main_widget.add<GUI::ScrollableContainerWidget>(); + scrollable_container.set_widget(timelines_widget.ptr()); + main_widget.add<ProcessPickerWidget>(*profile); auto& tab_widget = main_widget.add<GUI::TabWidget>(); |