summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-05-06 18:44:31 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-06 22:18:45 +0200
commit9273054b2b9591ddaebd63c910fe28616b4f7f7d (patch)
treef1beb7ad88880453854718690fe1d507bae1c2b5
parent017da44ac2afb084d95f28645d956dbcc79ca214 (diff)
downloadserenity-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.cpp15
-rw-r--r--Userland/DevTools/Profiler/ProfileTimelineWidget.h4
-rw-r--r--Userland/DevTools/Profiler/main.cpp20
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>();