mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:37:35 +00:00
Profiler: Add a new "Samples" view to the main UI
You can now view the individual samples in a profile one by one with the new "Samples" view. The "old" main view moves into a "Call Tree" tab (but it remains the default view.) When you select a sample in the samples view, we show you the full symbolicated backtrace in a separate view on the right hand side. :^)
This commit is contained in:
parent
2c1f71055f
commit
1fb1279cfd
8 changed files with 369 additions and 11 deletions
|
@ -27,6 +27,7 @@
|
|||
#include "Profile.h"
|
||||
#include "DisassemblyModel.h"
|
||||
#include "ProfileModel.h"
|
||||
#include "SamplesModel.h"
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/MappedFile.h>
|
||||
|
@ -55,6 +56,7 @@ Profile::Profile(String executable_path, Vector<Event> events, NonnullOwnPtr<Lib
|
|||
m_last_timestamp = m_events.last().timestamp;
|
||||
|
||||
m_model = ProfileModel::create(*this);
|
||||
m_samples_model = SamplesModel::create(*this);
|
||||
|
||||
for (auto& event : m_events) {
|
||||
m_deepest_stack_depth = max((u32)event.frames.size(), m_deepest_stack_depth);
|
||||
|
@ -72,6 +74,11 @@ GUI::Model& Profile::model()
|
|||
return *m_model;
|
||||
}
|
||||
|
||||
GUI::Model& Profile::samples_model()
|
||||
{
|
||||
return *m_samples_model;
|
||||
}
|
||||
|
||||
void Profile::rebuild_tree()
|
||||
{
|
||||
u32 filtered_event_count = 0;
|
||||
|
@ -91,18 +98,14 @@ void Profile::rebuild_tree()
|
|||
|
||||
HashTable<FlatPtr> live_allocations;
|
||||
|
||||
for (auto& event : m_events) {
|
||||
if (has_timestamp_filter_range()) {
|
||||
auto timestamp = event.timestamp;
|
||||
if (timestamp < m_timestamp_filter_range_start || timestamp > m_timestamp_filter_range_end)
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_event_in_filter_range([&](auto& event) {
|
||||
if (event.type == "malloc")
|
||||
live_allocations.set(event.ptr);
|
||||
else if (event.type == "free")
|
||||
live_allocations.remove(event.ptr);
|
||||
}
|
||||
});
|
||||
|
||||
Optional<size_t> first_filtered_event_index;
|
||||
|
||||
for (size_t event_index = 0; event_index < m_events.size(); ++event_index) {
|
||||
auto& event = m_events.at(event_index);
|
||||
|
@ -112,6 +115,9 @@ void Profile::rebuild_tree()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!first_filtered_event_index.has_value())
|
||||
first_filtered_event_index = event_index;
|
||||
|
||||
if (event.type == "malloc" && !live_allocations.contains(event.ptr))
|
||||
continue;
|
||||
|
||||
|
@ -197,6 +203,7 @@ void Profile::rebuild_tree()
|
|||
sort_profile_nodes(roots);
|
||||
|
||||
m_filtered_event_count = filtered_event_count;
|
||||
m_first_filtered_event_index = first_filtered_event_index.value_or(0);
|
||||
m_roots = move(roots);
|
||||
m_model->update();
|
||||
}
|
||||
|
@ -307,6 +314,7 @@ void Profile::set_timestamp_filter_range(u64 start, u64 end)
|
|||
m_timestamp_filter_range_end = max(start, end);
|
||||
|
||||
rebuild_tree();
|
||||
m_samples_model->update();
|
||||
}
|
||||
|
||||
void Profile::clear_timestamp_filter_range()
|
||||
|
@ -315,6 +323,7 @@ void Profile::clear_timestamp_filter_range()
|
|||
return;
|
||||
m_has_timestamp_filter_range = false;
|
||||
rebuild_tree();
|
||||
m_samples_model->update();
|
||||
}
|
||||
|
||||
void Profile::set_inverted(bool inverted)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue