mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:27:45 +00:00
Profiler: Move ELF object name to its own profile graph column
This way you don't have to look at all the library names if you don't want to. Since we're pretty good about namespacing our things, the library names are slightly redundant information.
This commit is contained in:
parent
2f0ea9ae33
commit
340180ba05
4 changed files with 43 additions and 24 deletions
|
@ -28,12 +28,12 @@
|
||||||
#include "DisassemblyModel.h"
|
#include "DisassemblyModel.h"
|
||||||
#include "ProfileModel.h"
|
#include "ProfileModel.h"
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
|
#include <AK/LexicalPath.h>
|
||||||
#include <AK/MappedFile.h>
|
#include <AK/MappedFile.h>
|
||||||
#include <AK/QuickSort.h>
|
#include <AK/QuickSort.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <LibELF/Image.h>
|
#include <LibELF/Image.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
static void sort_profile_nodes(Vector<NonnullRefPtr<ProfileNode>>& nodes)
|
static void sort_profile_nodes(Vector<NonnullRefPtr<ProfileNode>>& nodes)
|
||||||
|
@ -77,14 +77,14 @@ void Profile::rebuild_tree()
|
||||||
u32 filtered_event_count = 0;
|
u32 filtered_event_count = 0;
|
||||||
Vector<NonnullRefPtr<ProfileNode>> roots;
|
Vector<NonnullRefPtr<ProfileNode>> roots;
|
||||||
|
|
||||||
auto find_or_create_root = [&roots](const String& symbol, u32 address, u32 offset, u64 timestamp) -> ProfileNode& {
|
auto find_or_create_root = [&roots](FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp) -> ProfileNode& {
|
||||||
for (size_t i = 0; i < roots.size(); ++i) {
|
for (size_t i = 0; i < roots.size(); ++i) {
|
||||||
auto& root = roots[i];
|
auto& root = roots[i];
|
||||||
if (root->symbol() == symbol) {
|
if (root->symbol() == symbol) {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto new_root = ProfileNode::create(symbol, address, offset, timestamp);
|
auto new_root = ProfileNode::create(move(object_name), move(symbol), address, offset, timestamp);
|
||||||
roots.append(new_root);
|
roots.append(new_root);
|
||||||
return new_root;
|
return new_root;
|
||||||
};
|
};
|
||||||
|
@ -135,6 +135,7 @@ void Profile::rebuild_tree()
|
||||||
if (!m_show_top_functions) {
|
if (!m_show_top_functions) {
|
||||||
ProfileNode* node = nullptr;
|
ProfileNode* node = nullptr;
|
||||||
for_each_frame([&](const Frame& frame, bool is_innermost_frame) {
|
for_each_frame([&](const Frame& frame, bool is_innermost_frame) {
|
||||||
|
auto& object_name = frame.object_name;
|
||||||
auto& symbol = frame.symbol;
|
auto& symbol = frame.symbol;
|
||||||
auto& address = frame.address;
|
auto& address = frame.address;
|
||||||
auto& offset = frame.offset;
|
auto& offset = frame.offset;
|
||||||
|
@ -143,9 +144,9 @@ void Profile::rebuild_tree()
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
node = &find_or_create_root(symbol, address, offset, event.timestamp);
|
node = &find_or_create_root(object_name, symbol, address, offset, event.timestamp);
|
||||||
else
|
else
|
||||||
node = &node->find_or_create_child(symbol, address, offset, event.timestamp);
|
node = &node->find_or_create_child(object_name, symbol, address, offset, event.timestamp);
|
||||||
|
|
||||||
node->increment_event_count();
|
node->increment_event_count();
|
||||||
if (is_innermost_frame) {
|
if (is_innermost_frame) {
|
||||||
|
@ -160,6 +161,7 @@ void Profile::rebuild_tree()
|
||||||
ProfileNode* root = nullptr;
|
ProfileNode* root = nullptr;
|
||||||
for (size_t j = i; j < event.frames.size(); ++j) {
|
for (size_t j = i; j < event.frames.size(); ++j) {
|
||||||
auto& frame = event.frames.at(j);
|
auto& frame = event.frames.at(j);
|
||||||
|
auto& object_name = frame.object_name;
|
||||||
auto& symbol = frame.symbol;
|
auto& symbol = frame.symbol;
|
||||||
auto& address = frame.address;
|
auto& address = frame.address;
|
||||||
auto& offset = frame.offset;
|
auto& offset = frame.offset;
|
||||||
|
@ -167,11 +169,11 @@ void Profile::rebuild_tree()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
node = &find_or_create_root(symbol, address, offset, event.timestamp);
|
node = &find_or_create_root(object_name, symbol, address, offset, event.timestamp);
|
||||||
root = node;
|
root = node;
|
||||||
root->will_track_seen_events(m_events.size());
|
root->will_track_seen_events(m_events.size());
|
||||||
} else {
|
} else {
|
||||||
node = &node->find_or_create_child(symbol, address, offset, event.timestamp);
|
node = &node->find_or_create_child(object_name, symbol, address, offset, event.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!root->has_seen_event(event_index)) {
|
if (!root->has_seen_event(event_index)) {
|
||||||
|
@ -257,6 +259,7 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St
|
||||||
auto& frame = stack_array.at(i);
|
auto& frame = stack_array.at(i);
|
||||||
auto ptr = frame.to_number<u32>();
|
auto ptr = frame.to_number<u32>();
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
FlyString object_name;
|
||||||
String symbol;
|
String symbol;
|
||||||
|
|
||||||
if (ptr >= 0xc0000000) {
|
if (ptr >= 0xc0000000) {
|
||||||
|
@ -266,10 +269,15 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St
|
||||||
symbol = "??";
|
symbol = "??";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
symbol = library_metadata->symbolicate(ptr, offset);
|
if (auto* library = library_metadata->library_containing(ptr)) {
|
||||||
|
object_name = library->name;
|
||||||
|
symbol = library->elf.symbolicate(ptr - library->base, &offset);
|
||||||
|
} else {
|
||||||
|
symbol = "??";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.frames.append({ symbol, ptr, offset });
|
event.frames.append({ object_name, symbol, ptr, offset });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.frames.size() < 2)
|
if (event.frames.size() < 2)
|
||||||
|
@ -391,9 +399,17 @@ const Profile::LibraryMetadata::Library* Profile::LibraryMetadata::library_conta
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Profile::LibraryMetadata::symbolicate(FlatPtr ptr, u32& offset) const
|
ProfileNode::ProfileNode(const String& object_name, String symbol, u32 address, u32 offset, u64 timestamp)
|
||||||
|
: m_symbol(move(symbol))
|
||||||
|
, m_address(address)
|
||||||
|
, m_offset(offset)
|
||||||
|
, m_timestamp(timestamp)
|
||||||
{
|
{
|
||||||
if (auto* library = library_containing(ptr))
|
String object;
|
||||||
return String::formatted("[{}] {}", library->name, library->elf.symbolicate(ptr - library->base, &offset));
|
if (object_name.ends_with(": .text")) {
|
||||||
return "??";
|
object = object_name.view().substring_view(0, object_name.length() - 7);
|
||||||
|
} else {
|
||||||
|
object = object_name;
|
||||||
|
}
|
||||||
|
m_object_name = LexicalPath(object).basename();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Bitmap.h>
|
#include <AK/Bitmap.h>
|
||||||
|
#include <AK/FlyString.h>
|
||||||
#include <AK/JsonArray.h>
|
#include <AK/JsonArray.h>
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
#include <AK/JsonValue.h>
|
#include <AK/JsonValue.h>
|
||||||
|
@ -43,9 +44,9 @@ class DisassemblyModel;
|
||||||
|
|
||||||
class ProfileNode : public RefCounted<ProfileNode> {
|
class ProfileNode : public RefCounted<ProfileNode> {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<ProfileNode> create(const String& symbol, u32 address, u32 offset, u64 timestamp)
|
static NonnullRefPtr<ProfileNode> create(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp)
|
||||||
{
|
{
|
||||||
return adopt(*new ProfileNode(symbol, address, offset, timestamp));
|
return adopt(*new ProfileNode(move(object_name), move(symbol), address, offset, timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// These functions are only relevant for root nodes
|
// These functions are only relevant for root nodes
|
||||||
|
@ -57,6 +58,7 @@ public:
|
||||||
bool has_seen_event(size_t event_index) const { return m_seen_events.get(event_index); }
|
bool has_seen_event(size_t event_index) const { return m_seen_events.get(event_index); }
|
||||||
void did_see_event(size_t event_index) { m_seen_events.set(event_index, true); }
|
void did_see_event(size_t event_index) { m_seen_events.set(event_index, true); }
|
||||||
|
|
||||||
|
const FlyString& object_name() const { return m_object_name; }
|
||||||
const String& symbol() const { return m_symbol; }
|
const String& symbol() const { return m_symbol; }
|
||||||
u32 address() const { return m_address; }
|
u32 address() const { return m_address; }
|
||||||
u32 offset() const { return m_offset; }
|
u32 offset() const { return m_offset; }
|
||||||
|
@ -77,7 +79,7 @@ public:
|
||||||
m_children.append(child);
|
m_children.append(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileNode& find_or_create_child(const String& symbol, u32 address, u32 offset, u64 timestamp)
|
ProfileNode& find_or_create_child(FlyString object_name, String symbol, u32 address, u32 offset, u64 timestamp)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_children.size(); ++i) {
|
for (size_t i = 0; i < m_children.size(); ++i) {
|
||||||
auto& child = m_children[i];
|
auto& child = m_children[i];
|
||||||
|
@ -85,7 +87,7 @@ public:
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto new_child = ProfileNode::create(symbol, address, offset, timestamp);
|
auto new_child = ProfileNode::create(move(object_name), move(symbol), address, offset, timestamp);
|
||||||
add_child(new_child);
|
add_child(new_child);
|
||||||
return new_child;
|
return new_child;
|
||||||
};
|
};
|
||||||
|
@ -109,15 +111,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ProfileNode(const String& symbol, u32 address, u32 offset, u64 timestamp)
|
explicit ProfileNode(const String& object_name, String symbol, u32 address, u32 offset, u64 timestamp);
|
||||||
: m_symbol(symbol)
|
|
||||||
, m_address(address)
|
|
||||||
, m_offset(offset)
|
|
||||||
, m_timestamp(timestamp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileNode* m_parent { nullptr };
|
ProfileNode* m_parent { nullptr };
|
||||||
|
FlyString m_object_name;
|
||||||
String m_symbol;
|
String m_symbol;
|
||||||
u32 m_address { 0 };
|
u32 m_address { 0 };
|
||||||
u32 m_offset { 0 };
|
u32 m_offset { 0 };
|
||||||
|
@ -142,6 +139,7 @@ public:
|
||||||
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
|
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
|
FlyString object_name;
|
||||||
String symbol;
|
String symbol;
|
||||||
u32 address { 0 };
|
u32 address { 0 };
|
||||||
u32 offset { 0 };
|
u32 offset { 0 };
|
||||||
|
|
|
@ -100,6 +100,8 @@ String ProfileModel::column_name(int column) const
|
||||||
return m_profile.show_percentages() ? "% Samples" : "# Samples";
|
return m_profile.show_percentages() ? "% Samples" : "# Samples";
|
||||||
case Column::SelfCount:
|
case Column::SelfCount:
|
||||||
return m_profile.show_percentages() ? "% Self" : "# Self";
|
return m_profile.show_percentages() ? "% Self" : "# Self";
|
||||||
|
case Column::ObjectName:
|
||||||
|
return "Object";
|
||||||
case Column::StackFrame:
|
case Column::StackFrame:
|
||||||
return "Stack Frame";
|
return "Stack Frame";
|
||||||
default:
|
default:
|
||||||
|
@ -134,6 +136,8 @@ GUI::Variant ProfileModel::data(const GUI::ModelIndex& index, GUI::ModelRole rol
|
||||||
return ((float)node->self_count() / (float)m_profile.filtered_event_count()) * 100.0f;
|
return ((float)node->self_count() / (float)m_profile.filtered_event_count()) * 100.0f;
|
||||||
return node->self_count();
|
return node->self_count();
|
||||||
}
|
}
|
||||||
|
if (index.column() == Column::ObjectName)
|
||||||
|
return node->object_name();
|
||||||
if (index.column() == Column::StackFrame)
|
if (index.column() == Column::StackFrame)
|
||||||
return node->symbol();
|
return node->symbol();
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
enum Column {
|
enum Column {
|
||||||
SampleCount,
|
SampleCount,
|
||||||
SelfCount,
|
SelfCount,
|
||||||
|
ObjectName,
|
||||||
StackFrame,
|
StackFrame,
|
||||||
__Count
|
__Count
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue