From 210d2d270d3a71e215350b1c78b1e9f0f614d8cf Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 8 May 2021 01:33:43 +0200 Subject: [PATCH] Profiler: Let the user select more than one process --- Userland/DevTools/Profiler/Profile.cpp | 37 +++++++++++++++++++------- Userland/DevTools/Profiler/Profile.h | 21 ++++++++++----- Userland/DevTools/Profiler/main.cpp | 10 +++---- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/Userland/DevTools/Profiler/Profile.cpp b/Userland/DevTools/Profiler/Profile.cpp index 948ac92bf4..bd49eade17 100644 --- a/Userland/DevTools/Profiler/Profile.cpp +++ b/Userland/DevTools/Profiler/Profile.cpp @@ -376,26 +376,39 @@ void Profile::clear_timestamp_filter_range() m_samples_model->update(); } -void Profile::set_process_filter(pid_t pid, u64 start_valid, u64 end_valid) +void Profile::add_process_filter(pid_t pid, u64 start_valid, u64 end_valid) { - if (m_has_process_filter && m_process_filter_pid == pid && m_process_filter_start_valid == start_valid && m_process_filter_end_valid == end_valid) + auto filter = ProcessFilter { pid, start_valid, end_valid }; + if (m_process_filters.contains_slow(filter)) return; - m_has_process_filter = true; - - m_process_filter_pid = pid; - m_process_filter_start_valid = start_valid; - m_process_filter_end_valid = end_valid; + m_process_filters.append(move(filter)); rebuild_tree(); if (m_disassembly_model) m_disassembly_model->update(); m_samples_model->update(); } + +void Profile::remove_process_filter(pid_t pid, u64 start_valid, u64 end_valid) +{ + auto filter = ProcessFilter { pid, start_valid, end_valid }; + if (!m_process_filters.contains_slow(filter)) + return; + m_process_filters.remove_first_matching([&filter](ProcessFilter const& other_filter) { + return other_filter == filter; + }); + + rebuild_tree(); + if (m_disassembly_model) + m_disassembly_model->update(); + m_samples_model->update(); +} + void Profile::clear_process_filter() { - if (!m_has_process_filter) + if (m_process_filters.is_empty()) return; - m_has_process_filter = false; + m_process_filters.clear(); rebuild_tree(); if (m_disassembly_model) m_disassembly_model->update(); @@ -407,7 +420,11 @@ bool Profile::process_filter_contains(pid_t pid, u32 timestamp) if (!has_process_filter()) return true; - return (pid == m_process_filter_pid && timestamp >= m_process_filter_start_valid && timestamp <= m_process_filter_end_valid); + for (auto const& process_filter : m_process_filters) + if (pid == process_filter.pid && timestamp >= process_filter.start_valid && timestamp <= process_filter.end_valid) + return true; + + return false; } void Profile::set_inverted(bool inverted) diff --git a/Userland/DevTools/Profiler/Profile.h b/Userland/DevTools/Profiler/Profile.h index 4008884b92..cffc5f91f1 100644 --- a/Userland/DevTools/Profiler/Profile.h +++ b/Userland/DevTools/Profiler/Profile.h @@ -116,6 +116,17 @@ private: Bitmap m_seen_events; }; +struct ProcessFilter { + pid_t pid { 0 }; + u64 start_valid { 0 }; + u64 end_valid { 0 }; + + bool operator==(ProcessFilter const& rhs) const + { + return pid == rhs.pid && start_valid == rhs.start_valid && end_valid == rhs.end_valid; + } +}; + class Profile { public: static Result, String> load_from_perfcore_file(const StringView& path); @@ -171,9 +182,10 @@ public: void clear_timestamp_filter_range(); bool has_timestamp_filter_range() const { return m_has_timestamp_filter_range; } - void set_process_filter(pid_t pid, u64 start_valid, u64 end_valid); + void add_process_filter(pid_t pid, u64 start_valid, u64 end_valid); + void remove_process_filter(pid_t pid, u64 start_valid, u64 end_valid); void clear_process_filter(); - bool has_process_filter() const { return m_has_process_filter; } + bool has_process_filter() const { return !m_process_filters.is_empty(); } bool process_filter_contains(pid_t pid, u32 timestamp); bool is_inverted() const { return m_inverted; } @@ -222,10 +234,7 @@ private: u64 m_timestamp_filter_range_start { 0 }; u64 m_timestamp_filter_range_end { 0 }; - bool m_has_process_filter { false }; - pid_t m_process_filter_pid { 0 }; - u64 m_process_filter_start_valid { 0 }; - u64 m_process_filter_end_valid { 0 }; + Vector m_process_filters; u32 m_deepest_stack_depth { 0 }; bool m_inverted { false }; diff --git a/Userland/DevTools/Profiler/main.cpp b/Userland/DevTools/Profiler/main.cpp index 3b322f008a..83eb37cdcb 100644 --- a/Userland/DevTools/Profiler/main.cpp +++ b/Userland/DevTools/Profiler/main.cpp @@ -110,11 +110,11 @@ int main(int argc, char** argv) auto& timeline_header = timeline_header_container->add(*profile, process); timeline_header.set_shrink_to_fit(true); timeline_header.on_selection_change = [&](bool selected) { - if (selected) { - auto end_valid = process.end_valid == 0 ? profile->last_timestamp() : process.end_valid; - profile->set_process_filter(process.pid, process.start_valid, end_valid); - } else - profile->clear_process_filter(); + auto end_valid = process.end_valid == 0 ? profile->last_timestamp() : process.end_valid; + if (selected) + profile->add_process_filter(process.pid, process.start_valid, end_valid); + else + profile->remove_process_filter(process.pid, process.start_valid, end_valid); timeline_header_container->for_each_child_widget([](auto& other_timeline_header) { static_cast(other_timeline_header).update_selection();