diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-05-13 14:29:15 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-14 00:35:57 +0200 |
commit | c534f176bc1d0f2d89c90e9e7320e4782eaba833 (patch) | |
tree | 16a1f3f5850122eb49f05b456659ac40e6637f6a | |
parent | a11a1cd4d6bfaac0ff76b8eb048acf5bdb9be4c7 (diff) | |
download | serenity-c534f176bc1d0f2d89c90e9e7320e4782eaba833.zip |
Profiler: Add histogram for sample counts
Previously Profiler would use the stack depth to draw the timeline
graphs. This is not an accurate representation of whether a thread
is "busy" or not. Instead this updates the timelines to use the
sample count.
-rw-r--r-- | Userland/DevTools/Profiler/Histogram.h | 42 | ||||
-rw-r--r-- | Userland/DevTools/Profiler/TimelineTrack.cpp | 40 |
2 files changed, 75 insertions, 7 deletions
diff --git a/Userland/DevTools/Profiler/Histogram.h b/Userland/DevTools/Profiler/Histogram.h new file mode 100644 index 0000000000..3380e7741a --- /dev/null +++ b/Userland/DevTools/Profiler/Histogram.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Vector.h> + +template<typename Timestamp = u64, typename Value = u16, size_t inline_capacity = 4096> +class Histogram { +public: + Histogram(Timestamp start, Timestamp end, size_t bucket_count) + : m_start(start) + , m_end(end) + { + m_buckets.resize(bucket_count); + } + + void insert(Timestamp const& timestamp, Value value = 1) + { + VERIFY(timestamp >= m_start && timestamp <= m_end); + auto bucket = (timestamp - m_start) * (m_buckets.size() - 1) / (m_end - m_start); + m_buckets[bucket] += value; + } + + Value at(size_t index) const + { + return m_buckets[index]; + } + + size_t size() const + { + return m_buckets.size(); + } + +private: + Timestamp m_start { 0 }; + Timestamp m_end { 0 }; + Vector<Value, inline_capacity> m_buckets; +}; diff --git a/Userland/DevTools/Profiler/TimelineTrack.cpp b/Userland/DevTools/Profiler/TimelineTrack.cpp index 7a09d54db0..cebb1be495 100644 --- a/Userland/DevTools/Profiler/TimelineTrack.cpp +++ b/Userland/DevTools/Profiler/TimelineTrack.cpp @@ -5,6 +5,7 @@ */ #include "TimelineTrack.h" +#include "Histogram.h" #include "Profile.h" #include "TimelineView.h" #include <LibGUI/Painter.h> @@ -57,7 +58,11 @@ void TimelineTrack::paint_event(GUI::PaintEvent& event) }; float column_width = (float)frame_inner_rect().width() / (float)m_profile.length_in_ms(); - float frame_height = (float)frame_inner_rect().height() / (float)m_profile.deepest_stack_depth(); + size_t columns = frame_inner_rect().width() / column_width; + + Histogram kernel_histogram { start_of_trace, end_of_trace, columns }; + Histogram usermode_histogram { start_of_trace, end_of_trace, columns }; + auto bucket_count = kernel_histogram.size(); for (auto& event : m_profile.events()) { if (event.pid != m_process.pid) @@ -66,16 +71,37 @@ void TimelineTrack::paint_event(GUI::PaintEvent& event) if (!m_process.valid_at(event.timestamp)) continue; - u64 t = clamp_timestamp(event.timestamp) - start_of_trace; + auto& histogram = event.in_kernel ? kernel_histogram : usermode_histogram; + histogram.insert(clamp_timestamp(event.timestamp), 1); + } + + decltype(kernel_histogram.at(0)) max_value = 0; + for (size_t bucket = 0; bucket < bucket_count; bucket++) { + auto value = kernel_histogram.at(bucket) + usermode_histogram.at(bucket); + if (value > max_value) + max_value = value; + } + + float frame_height = (float)frame_inner_rect().height() / (float)max_value; + + for (size_t bucket = 0; bucket < bucket_count; bucket++) { + auto kernel_value = kernel_histogram.at(bucket); + auto usermode_value = usermode_histogram.at(bucket); + if (kernel_value + usermode_value == 0) + continue; + + auto t = bucket; + int x = (int)((float)t * column_width); int cw = max(1, (int)column_width); - int column_height = frame_inner_rect().height() - (int)((float)event.frames.size() * frame_height); + int kernel_column_height = frame_inner_rect().height() - (int)((float)kernel_value * frame_height); + int usermode_column_height = frame_inner_rect().height() - (int)((float)(kernel_value + usermode_value) * frame_height); - bool in_kernel = event.in_kernel; - Color color = in_kernel ? Color::from_rgb(0xc25e5a) : Color::from_rgb(0x5a65c2); - for (int i = 1; i <= cw; ++i) - painter.draw_line({ x + i, frame_thickness() + column_height }, { x + i, height() - frame_thickness() * 2 }, color); + constexpr auto kernel_color = Color::from_rgb(0xc25e5a); + constexpr auto usermode_color = Color::from_rgb(0x5a65c2); + painter.fill_rect({ x, frame_thickness() + usermode_column_height, cw, height() - frame_thickness() * 2 }, usermode_color); + painter.fill_rect({ x, frame_thickness() + kernel_column_height, cw, height() - frame_thickness() * 2 }, kernel_color); } u64 normalized_start_time = clamp_timestamp(min(m_view.select_start_time(), m_view.select_end_time())); |