1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:57:34 +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:
Andreas Kling 2021-02-27 17:45:41 +01:00
parent 2f0ea9ae33
commit 340180ba05
4 changed files with 43 additions and 24 deletions

View file

@ -28,12 +28,12 @@
#include "DisassemblyModel.h"
#include "ProfileModel.h"
#include <AK/HashTable.h>
#include <AK/LexicalPath.h>
#include <AK/MappedFile.h>
#include <AK/QuickSort.h>
#include <AK/RefPtr.h>
#include <LibCore/File.h>
#include <LibELF/Image.h>
#include <stdio.h>
#include <sys/stat.h>
static void sort_profile_nodes(Vector<NonnullRefPtr<ProfileNode>>& nodes)
@ -77,14 +77,14 @@ void Profile::rebuild_tree()
u32 filtered_event_count = 0;
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) {
auto& root = roots[i];
if (root->symbol() == symbol) {
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);
return new_root;
};
@ -135,6 +135,7 @@ void Profile::rebuild_tree()
if (!m_show_top_functions) {
ProfileNode* node = nullptr;
for_each_frame([&](const Frame& frame, bool is_innermost_frame) {
auto& object_name = frame.object_name;
auto& symbol = frame.symbol;
auto& address = frame.address;
auto& offset = frame.offset;
@ -143,9 +144,9 @@ void Profile::rebuild_tree()
return IterationDecision::Break;
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
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();
if (is_innermost_frame) {
@ -160,6 +161,7 @@ void Profile::rebuild_tree()
ProfileNode* root = nullptr;
for (size_t j = i; j < event.frames.size(); ++j) {
auto& frame = event.frames.at(j);
auto& object_name = frame.object_name;
auto& symbol = frame.symbol;
auto& address = frame.address;
auto& offset = frame.offset;
@ -167,11 +169,11 @@ void Profile::rebuild_tree()
break;
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->will_track_seen_events(m_events.size());
} 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)) {
@ -257,6 +259,7 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St
auto& frame = stack_array.at(i);
auto ptr = frame.to_number<u32>();
u32 offset = 0;
FlyString object_name;
String symbol;
if (ptr >= 0xc0000000) {
@ -266,10 +269,15 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St
symbol = "??";
}
} 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)
@ -391,9 +399,17 @@ const Profile::LibraryMetadata::Library* Profile::LibraryMetadata::library_conta
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))
return String::formatted("[{}] {}", library->name, library->elf.symbolicate(ptr - library->base, &offset));
return "??";
String object;
if (object_name.ends_with(": .text")) {
object = object_name.view().substring_view(0, object_name.length() - 7);
} else {
object = object_name;
}
m_object_name = LexicalPath(object).basename();
}

View file

@ -27,6 +27,7 @@
#pragma once
#include <AK/Bitmap.h>
#include <AK/FlyString.h>
#include <AK/JsonArray.h>
#include <AK/JsonObject.h>
#include <AK/JsonValue.h>
@ -43,9 +44,9 @@ class DisassemblyModel;
class ProfileNode : public RefCounted<ProfileNode> {
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
@ -57,6 +58,7 @@ public:
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); }
const FlyString& object_name() const { return m_object_name; }
const String& symbol() const { return m_symbol; }
u32 address() const { return m_address; }
u32 offset() const { return m_offset; }
@ -77,7 +79,7 @@ public:
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) {
auto& child = m_children[i];
@ -85,7 +87,7 @@ public:
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);
return new_child;
};
@ -109,15 +111,10 @@ public:
}
private:
explicit ProfileNode(const String& symbol, u32 address, u32 offset, u64 timestamp)
: m_symbol(symbol)
, m_address(address)
, m_offset(offset)
, m_timestamp(timestamp)
{
}
explicit ProfileNode(const String& object_name, String symbol, u32 address, u32 offset, u64 timestamp);
ProfileNode* m_parent { nullptr };
FlyString m_object_name;
String m_symbol;
u32 m_address { 0 };
u32 m_offset { 0 };
@ -142,6 +139,7 @@ public:
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
struct Frame {
FlyString object_name;
String symbol;
u32 address { 0 };
u32 offset { 0 };

View file

@ -100,6 +100,8 @@ String ProfileModel::column_name(int column) const
return m_profile.show_percentages() ? "% Samples" : "# Samples";
case Column::SelfCount:
return m_profile.show_percentages() ? "% Self" : "# Self";
case Column::ObjectName:
return "Object";
case Column::StackFrame:
return "Stack Frame";
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 node->self_count();
}
if (index.column() == Column::ObjectName)
return node->object_name();
if (index.column() == Column::StackFrame)
return node->symbol();
return {};

View file

@ -40,6 +40,7 @@ public:
enum Column {
SampleCount,
SelfCount,
ObjectName,
StackFrame,
__Count
};