mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 06:57:46 +00:00
Kernel+Profiler: Capture metadata about all profiled processes
The perfcore file format was previously limited to a single process since the pid/executable/regions data was top-level in the JSON. This patch moves the process-specific data into a top-level array named "processes" and we now add entries for each process that has been sampled during the profile run. This makes it possible to see samples from multiple threads when viewing a perfcore file with Profiler. This is extremely cool! :^)
This commit is contained in:
parent
ea500dd3e3
commit
5e7abea31e
11 changed files with 223 additions and 102 deletions
|
@ -39,15 +39,50 @@
|
|||
#include <LibGUI/Forward.h>
|
||||
#include <LibGUI/ModelIndex.h>
|
||||
|
||||
class ProfileModel;
|
||||
class DisassemblyModel;
|
||||
class Profile;
|
||||
class ProfileModel;
|
||||
class SamplesModel;
|
||||
|
||||
class LibraryMetadata {
|
||||
public:
|
||||
explicit LibraryMetadata(JsonArray regions);
|
||||
|
||||
struct Library {
|
||||
FlatPtr base;
|
||||
size_t size;
|
||||
String name;
|
||||
NonnullRefPtr<MappedFile> file;
|
||||
ELF::Image elf;
|
||||
};
|
||||
|
||||
const Library* library_containing(FlatPtr) const;
|
||||
|
||||
private:
|
||||
mutable HashMap<String, OwnPtr<Library>> m_libraries;
|
||||
JsonArray m_regions;
|
||||
};
|
||||
|
||||
struct Process {
|
||||
pid_t pid {};
|
||||
String executable;
|
||||
HashTable<int> threads;
|
||||
|
||||
struct Region {
|
||||
String name;
|
||||
FlatPtr base {};
|
||||
size_t size {};
|
||||
};
|
||||
Vector<Region> regions;
|
||||
|
||||
NonnullOwnPtr<LibraryMetadata> library_metadata;
|
||||
};
|
||||
|
||||
class ProfileNode : public RefCounted<ProfileNode> {
|
||||
public:
|
||||
static NonnullRefPtr<ProfileNode> create(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp)
|
||||
static NonnullRefPtr<ProfileNode> create(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp, pid_t pid)
|
||||
{
|
||||
return adopt(*new ProfileNode(move(object_name), move(symbol), address, offset, timestamp));
|
||||
return adopt(*new ProfileNode(move(object_name), move(symbol), address, offset, timestamp, pid));
|
||||
}
|
||||
|
||||
// These functions are only relevant for root nodes
|
||||
|
@ -80,7 +115,7 @@ public:
|
|||
m_children.append(child);
|
||||
}
|
||||
|
||||
ProfileNode& find_or_create_child(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp)
|
||||
ProfileNode& find_or_create_child(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp, pid_t pid)
|
||||
{
|
||||
for (size_t i = 0; i < m_children.size(); ++i) {
|
||||
auto& child = m_children[i];
|
||||
|
@ -88,7 +123,7 @@ public:
|
|||
return child;
|
||||
}
|
||||
}
|
||||
auto new_child = ProfileNode::create(move(object_name), move(symbol), address, offset, timestamp);
|
||||
auto new_child = ProfileNode::create(move(object_name), move(symbol), address, offset, timestamp, pid);
|
||||
add_child(new_child);
|
||||
return new_child;
|
||||
};
|
||||
|
@ -111,12 +146,17 @@ public:
|
|||
m_events_per_address.set(address, it->value + 1);
|
||||
}
|
||||
|
||||
pid_t pid() const { return m_pid; }
|
||||
|
||||
const Process* process(Profile&) const;
|
||||
|
||||
private:
|
||||
explicit ProfileNode(const String& object_name, String symbol, u32 address, u32 offset, u64 timestamp);
|
||||
explicit ProfileNode(const String& object_name, String symbol, u32 address, u32 offset, u64 timestamp, pid_t);
|
||||
|
||||
ProfileNode* m_parent { nullptr };
|
||||
FlyString m_object_name;
|
||||
String m_symbol;
|
||||
pid_t m_pid { 0 };
|
||||
u32 m_address { 0 };
|
||||
u32 m_offset { 0 };
|
||||
u32 m_event_count { 0 };
|
||||
|
@ -136,6 +176,14 @@ public:
|
|||
GUI::Model& samples_model();
|
||||
GUI::Model* disassembly_model();
|
||||
|
||||
const Process* find_process(pid_t pid) const
|
||||
{
|
||||
auto it = m_processes.find_if([&](auto& entry) {
|
||||
return entry.pid == pid;
|
||||
});
|
||||
return it.is_end() ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
void set_disassembly_index(const GUI::ModelIndex&);
|
||||
|
||||
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
|
||||
|
@ -152,6 +200,7 @@ public:
|
|||
String type;
|
||||
FlatPtr ptr { 0 };
|
||||
size_t size { 0 };
|
||||
int tid { 0 };
|
||||
bool in_kernel { false };
|
||||
Vector<Frame> frames;
|
||||
};
|
||||
|
@ -178,29 +227,6 @@ public:
|
|||
bool show_percentages() const { return m_show_percentages; }
|
||||
void set_show_percentages(bool);
|
||||
|
||||
const String& executable_path() const { return m_executable_path; }
|
||||
|
||||
class LibraryMetadata {
|
||||
public:
|
||||
LibraryMetadata(JsonArray regions);
|
||||
|
||||
struct Library {
|
||||
FlatPtr base;
|
||||
size_t size;
|
||||
String name;
|
||||
NonnullRefPtr<MappedFile> file;
|
||||
ELF::Image elf;
|
||||
};
|
||||
|
||||
const Library* library_containing(FlatPtr) const;
|
||||
|
||||
private:
|
||||
mutable HashMap<String, OwnPtr<Library>> m_libraries;
|
||||
JsonArray m_regions;
|
||||
};
|
||||
|
||||
const LibraryMetadata& libraries() const { return *m_library_metadata; }
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_event_in_filter_range(Callback callback)
|
||||
{
|
||||
|
@ -215,12 +241,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Profile(String executable_path, Vector<Event>, NonnullOwnPtr<LibraryMetadata>);
|
||||
Profile(Vector<Process>, Vector<Event>);
|
||||
|
||||
void rebuild_tree();
|
||||
|
||||
String m_executable_path;
|
||||
|
||||
RefPtr<ProfileModel> m_model;
|
||||
RefPtr<SamplesModel> m_samples_model;
|
||||
RefPtr<DisassemblyModel> m_disassembly_model;
|
||||
|
@ -233,10 +257,9 @@ private:
|
|||
u64 m_first_timestamp { 0 };
|
||||
u64 m_last_timestamp { 0 };
|
||||
|
||||
Vector<Process> m_processes;
|
||||
Vector<Event> m_events;
|
||||
|
||||
NonnullOwnPtr<LibraryMetadata> m_library_metadata;
|
||||
|
||||
bool m_has_timestamp_filter_range { false };
|
||||
u64 m_timestamp_filter_range_start { 0 };
|
||||
u64 m_timestamp_filter_range_end { 0 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue