summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/DevTools/Profiler/CMakeLists.txt1
-rw-r--r--Userland/DevTools/Profiler/Profile.cpp16
-rw-r--r--Userland/DevTools/Profiler/Profile.h5
-rw-r--r--Userland/DevTools/Profiler/SignpostsModel.cpp95
-rw-r--r--Userland/DevTools/Profiler/SignpostsModel.h47
-rw-r--r--Userland/DevTools/Profiler/main.cpp15
6 files changed, 178 insertions, 1 deletions
diff --git a/Userland/DevTools/Profiler/CMakeLists.txt b/Userland/DevTools/Profiler/CMakeLists.txt
index f08eebaa15..427a8340cb 100644
--- a/Userland/DevTools/Profiler/CMakeLists.txt
+++ b/Userland/DevTools/Profiler/CMakeLists.txt
@@ -12,6 +12,7 @@ set(SOURCES
Profile.cpp
ProfileModel.cpp
SamplesModel.cpp
+ SignpostsModel.cpp
TimelineContainer.cpp
TimelineHeader.cpp
TimelineTrack.cpp
diff --git a/Userland/DevTools/Profiler/Profile.cpp b/Userland/DevTools/Profiler/Profile.cpp
index 104af281ca..432bcf17ba 100644
--- a/Userland/DevTools/Profiler/Profile.cpp
+++ b/Userland/DevTools/Profiler/Profile.cpp
@@ -45,6 +45,7 @@ Profile::Profile(Vector<Process> processes, Vector<Event> events)
m_model = ProfileModel::create(*this);
m_samples_model = SamplesModel::create(*this);
+ m_signposts_model = SignpostsModel::create(*this);
rebuild_tree();
}
@@ -59,6 +60,11 @@ GUI::Model& Profile::samples_model()
return *m_samples_model;
}
+GUI::Model& Profile::signposts_model()
+{
+ return *m_signposts_model;
+}
+
void Profile::rebuild_tree()
{
Vector<NonnullRefPtr<ProfileNode>> roots;
@@ -92,6 +98,7 @@ void Profile::rebuild_tree()
});
m_filtered_event_indices.clear();
+ m_filtered_signpost_indices.clear();
for (size_t event_index = 0; event_index < m_events.size(); ++event_index) {
auto& event = m_events.at(event_index);
@@ -105,8 +112,10 @@ void Profile::rebuild_tree()
if (!process_filter_contains(event.pid, event.serial))
continue;
- if (event.data.has<Event::SignpostData>())
+ if (event.data.has<Event::SignpostData>()) {
+ m_filtered_signpost_indices.append(event_index);
continue;
+ }
m_filtered_event_indices.append(event_index);
@@ -435,6 +444,7 @@ void Profile::set_timestamp_filter_range(u64 start, u64 end)
rebuild_tree();
m_samples_model->invalidate();
+ m_signposts_model->invalidate();
}
void Profile::clear_timestamp_filter_range()
@@ -444,6 +454,7 @@ void Profile::clear_timestamp_filter_range()
m_has_timestamp_filter_range = false;
rebuild_tree();
m_samples_model->invalidate();
+ m_signposts_model->invalidate();
}
void Profile::add_process_filter(pid_t pid, EventSerialNumber start_valid, EventSerialNumber end_valid)
@@ -457,6 +468,7 @@ void Profile::add_process_filter(pid_t pid, EventSerialNumber start_valid, Event
if (m_disassembly_model)
m_disassembly_model->invalidate();
m_samples_model->invalidate();
+ m_signposts_model->invalidate();
}
void Profile::remove_process_filter(pid_t pid, EventSerialNumber start_valid, EventSerialNumber end_valid)
@@ -472,6 +484,7 @@ void Profile::remove_process_filter(pid_t pid, EventSerialNumber start_valid, Ev
if (m_disassembly_model)
m_disassembly_model->invalidate();
m_samples_model->invalidate();
+ m_signposts_model->invalidate();
}
void Profile::clear_process_filter()
@@ -483,6 +496,7 @@ void Profile::clear_process_filter()
if (m_disassembly_model)
m_disassembly_model->invalidate();
m_samples_model->invalidate();
+ m_signposts_model->invalidate();
}
bool Profile::process_filter_contains(pid_t pid, EventSerialNumber serial)
diff --git a/Userland/DevTools/Profiler/Profile.h b/Userland/DevTools/Profiler/Profile.h
index f665513797..4bd65b4f5c 100644
--- a/Userland/DevTools/Profiler/Profile.h
+++ b/Userland/DevTools/Profiler/Profile.h
@@ -11,6 +11,7 @@
#include "Profile.h"
#include "ProfileModel.h"
#include "SamplesModel.h"
+#include "SignpostsModel.h"
#include <AK/Bitmap.h>
#include <AK/FlyString.h>
#include <AK/JsonArray.h>
@@ -142,6 +143,7 @@ public:
GUI::Model& model();
GUI::Model& samples_model();
+ GUI::Model& signposts_model();
GUI::Model* disassembly_model();
const Process* find_process(pid_t pid, EventSerialNumber serial) const
@@ -219,6 +221,7 @@ public:
Vector<Event> const& events() const { return m_events; }
const Vector<size_t>& filtered_event_indices() const { return m_filtered_event_indices; }
+ const Vector<size_t>& filtered_signpost_indices() const { return m_filtered_signpost_indices; }
u64 length_in_ms() const { return m_last_timestamp - m_first_timestamp; }
u64 first_timestamp() const { return m_first_timestamp; }
@@ -274,6 +277,7 @@ private:
RefPtr<ProfileModel> m_model;
RefPtr<SamplesModel> m_samples_model;
+ RefPtr<SignpostsModel> m_signposts_model;
RefPtr<DisassemblyModel> m_disassembly_model;
GUI::ModelIndex m_disassembly_index;
@@ -286,6 +290,7 @@ private:
Vector<Process> m_processes;
Vector<Event> m_events;
Vector<size_t> m_signpost_indices;
+ Vector<size_t> m_filtered_signpost_indices;
bool m_has_timestamp_filter_range { false };
u64 m_timestamp_filter_range_start { 0 };
diff --git a/Userland/DevTools/Profiler/SignpostsModel.cpp b/Userland/DevTools/Profiler/SignpostsModel.cpp
new file mode 100644
index 0000000000..e652cf4fce
--- /dev/null
+++ b/Userland/DevTools/Profiler/SignpostsModel.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "SignpostsModel.h"
+#include "Profile.h"
+#include <AK/StringBuilder.h>
+
+namespace Profiler {
+
+SignpostsModel::SignpostsModel(Profile& profile)
+ : m_profile(profile)
+{
+}
+
+SignpostsModel::~SignpostsModel()
+{
+}
+
+int SignpostsModel::row_count(const GUI::ModelIndex&) const
+{
+ return m_profile.filtered_signpost_indices().size();
+}
+
+int SignpostsModel::column_count(const GUI::ModelIndex&) const
+{
+ return Column::__Count;
+}
+
+String SignpostsModel::column_name(int column) const
+{
+ switch (column) {
+ case Column::SignpostIndex:
+ return "#";
+ case Column::Timestamp:
+ return "Timestamp";
+ case Column::ProcessID:
+ return "PID";
+ case Column::ThreadID:
+ return "TID";
+ case Column::ExecutableName:
+ return "Executable";
+ case Column::SignpostString:
+ return "String";
+ case Column::SignpostArgument:
+ return "Argument";
+ default:
+ VERIFY_NOT_REACHED();
+ }
+}
+
+GUI::Variant SignpostsModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
+{
+ u32 event_index = m_profile.filtered_signpost_indices()[index.row()];
+ auto& event = m_profile.events().at(event_index);
+
+ if (role == GUI::ModelRole::Custom) {
+ return event_index;
+ }
+
+ if (role == GUI::ModelRole::Display) {
+ if (index.column() == Column::SignpostIndex)
+ return event_index;
+
+ if (index.column() == Column::ProcessID)
+ return event.pid;
+
+ if (index.column() == Column::ThreadID)
+ return event.tid;
+
+ if (index.column() == Column::ExecutableName) {
+ if (auto* process = m_profile.find_process(event.pid, event.serial))
+ return process->executable;
+ return "";
+ }
+
+ if (index.column() == Column::Timestamp) {
+ return (u32)event.timestamp;
+ }
+
+ if (index.column() == Column::SignpostString) {
+ return event.data.get<Profile::Event::SignpostData>().string;
+ }
+
+ if (index.column() == Column::SignpostArgument) {
+ return event.data.get<Profile::Event::SignpostData>().arg;
+ }
+ return {};
+ }
+ return {};
+}
+
+}
diff --git a/Userland/DevTools/Profiler/SignpostsModel.h b/Userland/DevTools/Profiler/SignpostsModel.h
new file mode 100644
index 0000000000..5162c30694
--- /dev/null
+++ b/Userland/DevTools/Profiler/SignpostsModel.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibGUI/Model.h>
+
+namespace Profiler {
+
+class Profile;
+
+class SignpostsModel final : public GUI::Model {
+public:
+ static NonnullRefPtr<SignpostsModel> create(Profile& profile)
+ {
+ return adopt_ref(*new SignpostsModel(profile));
+ }
+
+ enum Column {
+ SignpostIndex,
+ Timestamp,
+ ProcessID,
+ ThreadID,
+ ExecutableName,
+ SignpostString,
+ SignpostArgument,
+ __Count
+ };
+
+ virtual ~SignpostsModel() override;
+
+ virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
+ virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
+ virtual String column_name(int) const override;
+ virtual GUI::Variant data(const GUI::ModelIndex&, GUI::ModelRole) const override;
+ virtual bool is_column_sortable(int) const override { return false; }
+
+private:
+ explicit SignpostsModel(Profile&);
+
+ Profile& m_profile;
+};
+
+}
diff --git a/Userland/DevTools/Profiler/main.cpp b/Userland/DevTools/Profiler/main.cpp
index 77a9383bed..e3de2f2bcc 100644
--- a/Userland/DevTools/Profiler/main.cpp
+++ b/Userland/DevTools/Profiler/main.cpp
@@ -176,6 +176,21 @@ int main(int argc, char** argv)
individual_sample_view.set_model(move(model));
};
+ auto& signposts_tab = tab_widget.add_tab<GUI::Widget>("Signposts");
+ signposts_tab.set_layout<GUI::VerticalBoxLayout>();
+ signposts_tab.layout()->set_margins({ 4, 4, 4, 4 });
+
+ auto& signposts_splitter = signposts_tab.add<GUI::HorizontalSplitter>();
+ auto& signposts_table_view = signposts_splitter.add<GUI::TableView>();
+ signposts_table_view.set_model(profile->signposts_model());
+
+ auto& individual_signpost_view = signposts_splitter.add<GUI::TableView>();
+ signposts_table_view.on_selection_change = [&] {
+ const auto& index = signposts_table_view.selection().first();
+ auto model = IndividualSampleModel::create(*profile, index.data(GUI::ModelRole::Custom).to_integer<size_t>());
+ individual_signpost_view.set_model(move(model));
+ };
+
const u64 start_of_trace = profile->first_timestamp();
const u64 end_of_trace = start_of_trace + profile->length_in_ms();
const auto clamp_timestamp = [start_of_trace, end_of_trace](u64 timestamp) -> u64 {