mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 14:35:08 +00:00
ProfileViewer: Begin work on a visualization tool for profiles :^)
We begin with a simple treeview that shows a recorded profile. To record and view a profile of a process with <PID>, simply do this: $ profile <PID> on ... wait while PID does something interesting ... $ profile <PID> off $ cat /proc/profile > my-profile.prof $ ProfileViewer my-profile.prof
This commit is contained in:
parent
0f393148da
commit
19d8c675f1
8 changed files with 350 additions and 0 deletions
83
DevTools/ProfileViewer/ProfileModel.cpp
Normal file
83
DevTools/ProfileViewer/ProfileModel.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include "ProfileModel.h"
|
||||
#include "Profile.h"
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
ProfileModel::ProfileModel(Profile& profile)
|
||||
: m_profile(profile)
|
||||
{
|
||||
m_frame_icon.set_bitmap_for_size(16, GraphicsBitmap::load_from_file("/res/icons/16x16/inspector-object.png"));
|
||||
}
|
||||
|
||||
ProfileModel::~ProfileModel()
|
||||
{
|
||||
}
|
||||
|
||||
GModelIndex ProfileModel::index(int row, int column, const GModelIndex& parent) const
|
||||
{
|
||||
if (!parent.is_valid()) {
|
||||
if (m_profile.roots().is_empty())
|
||||
return {};
|
||||
return create_index(row, column, &m_profile.roots().at(row));
|
||||
}
|
||||
auto& remote_parent = *static_cast<ProfileNode*>(parent.internal_data());
|
||||
return create_index(row, column, remote_parent.children().at(row).ptr());
|
||||
}
|
||||
|
||||
GModelIndex ProfileModel::parent_index(const GModelIndex& index) const
|
||||
{
|
||||
if (!index.is_valid())
|
||||
return {};
|
||||
auto& node = *static_cast<ProfileNode*>(index.internal_data());
|
||||
if (!node.parent())
|
||||
return {};
|
||||
|
||||
// NOTE: If the parent has no parent, it's a root, so we have to look among the remote roots.
|
||||
if (!node.parent()->parent()) {
|
||||
for (int row = 0; row < m_profile.roots().size(); ++row) {
|
||||
if (&m_profile.roots()[row] == node.parent())
|
||||
return create_index(row, 0, node.parent());
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
return {};
|
||||
}
|
||||
|
||||
for (int row = 0; row < node.parent()->parent()->children().size(); ++row) {
|
||||
if (node.parent()->parent()->children()[row].ptr() == node.parent())
|
||||
return create_index(row, 0, node.parent());
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
return {};
|
||||
}
|
||||
|
||||
int ProfileModel::row_count(const GModelIndex& index) const
|
||||
{
|
||||
if (!index.is_valid())
|
||||
return m_profile.roots().size();
|
||||
auto& node = *static_cast<ProfileNode*>(index.internal_data());
|
||||
return node.children().size();
|
||||
}
|
||||
|
||||
int ProfileModel::column_count(const GModelIndex&) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
GVariant ProfileModel::data(const GModelIndex& index, Role role) const
|
||||
{
|
||||
auto* node = static_cast<ProfileNode*>(index.internal_data());
|
||||
if (role == Role::Icon) {
|
||||
return m_frame_icon;
|
||||
}
|
||||
if (role == Role::Display) {
|
||||
return String::format("%s (%u)", node->symbol().characters(), node->sample_count());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void ProfileModel::update()
|
||||
{
|
||||
did_update();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue