mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 16:11:02 +08:00
Simple tree view
This commit is contained in:
parent
3d2ed40f54
commit
dfa583f410
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
bin
|
bin
|
||||||
build
|
*build*
|
||||||
.idea
|
.idea
|
||||||
|
*.user
|
||||||
|
@ -259,6 +259,11 @@ namespace profiler
|
|||||||
inline bool isCleared() const { return end >= begin; }
|
inline bool isCleared() const { return end >= begin; }
|
||||||
inline void finish(){ tick(end); }
|
inline void finish(){ tick(end); }
|
||||||
timestamp_t duration() const { return (end - begin); }
|
timestamp_t duration() const { return (end - begin); }
|
||||||
|
|
||||||
|
inline bool startsEarlierThan(const BaseBlockData& another) const {return this->begin < another.begin;}
|
||||||
|
inline bool endsEarlierThan(const BaseBlockData& another) const {return this->end < another.end;}
|
||||||
|
inline bool startsLaterThan(const BaseBlockData& another) const {return !this->startsEarlierThan(another);}
|
||||||
|
inline bool endsLaterThan(const BaseBlockData& another) const {return !this->endsEarlierThan(another);}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
@ -6,5 +6,5 @@ set(CMAKE_AUTOMOC ON)
|
|||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
add_executable(${PROJECT_NAME} main.cpp)
|
add_executable(${PROJECT_NAME} main.cpp treemodel.h treemodel.cpp treeitem.h treeitem.cpp)
|
||||||
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
|
target_link_libraries(${PROJECT_NAME} Qt5::Widgets easy_profiler)
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QFileSystemModel>
|
#include <QFileSystemModel>
|
||||||
|
#include "treemodel.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
|
||||||
QFileSystemModel *model = new QFileSystemModel;
|
//QFileSystemModel *model = new QFileSystemModel;
|
||||||
model->setRootPath(QDir::currentPath());
|
//model->setRootPath(QDir::currentPath());
|
||||||
|
|
||||||
|
QFile file("/home/yse/projects/easy_profiler/bin/test.prof");
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
TreeModel model(file.readAll());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
|
||||||
QTreeView *tree = new QTreeView();
|
QTreeView *tree = new QTreeView();
|
||||||
tree->setModel(model);
|
tree->setModel(&model);
|
||||||
|
|
||||||
tree->show();
|
tree->show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec( );
|
||||||
}
|
}
|
||||||
|
52
profiler_gui/treeitem.cpp
Normal file
52
profiler_gui/treeitem.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "treeitem.h"
|
||||||
|
|
||||||
|
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
|
||||||
|
{
|
||||||
|
m_parentItem = parent;
|
||||||
|
m_itemData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem::~TreeItem()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_childItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::appendChild(TreeItem *item)
|
||||||
|
{
|
||||||
|
m_childItems.append(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeItem::child(int row)
|
||||||
|
{
|
||||||
|
return m_childItems.value(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::childCount() const
|
||||||
|
{
|
||||||
|
return m_childItems.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::columnCount() const
|
||||||
|
{
|
||||||
|
return m_itemData.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeItem::data(int column) const
|
||||||
|
{
|
||||||
|
return m_itemData.value(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeItem::parentItem()
|
||||||
|
{
|
||||||
|
return m_parentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::row() const
|
||||||
|
{
|
||||||
|
if (m_parentItem)
|
||||||
|
return m_parentItem->m_childItems.indexOf(const_cast<TreeItem*>(this));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
28
profiler_gui/treeitem.h
Normal file
28
profiler_gui/treeitem.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef TREEITEM_H
|
||||||
|
#define TREEITEM_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
class TreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = 0);
|
||||||
|
~TreeItem();
|
||||||
|
|
||||||
|
void appendChild(TreeItem *child);
|
||||||
|
|
||||||
|
TreeItem *child(int row);
|
||||||
|
int childCount() const;
|
||||||
|
int columnCount() const;
|
||||||
|
QVariant data(int column) const;
|
||||||
|
int row() const;
|
||||||
|
TreeItem *parentItem();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<TreeItem*> m_childItems;
|
||||||
|
QList<QVariant> m_itemData;
|
||||||
|
TreeItem *m_parentItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TREEITEM_H
|
264
profiler_gui/treemodel.cpp
Normal file
264
profiler_gui/treemodel.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
#include "treeitem.h"
|
||||||
|
#include "treemodel.h"
|
||||||
|
#include "profiler/profiler.h"
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
TreeModel::TreeModel(const QByteArray &data, QObject *parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
{
|
||||||
|
QList<QVariant> rootData;
|
||||||
|
rootData << "Name" << "Duration usec" << "thread id" << "begin";
|
||||||
|
m_rootItem = new TreeItem(rootData);
|
||||||
|
setupModelData(data, m_rootItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeModel::~TreeModel()
|
||||||
|
{
|
||||||
|
delete m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
|
||||||
|
else
|
||||||
|
return m_rootItem->columnCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
|
||||||
|
return item->data(index.column());
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return QAbstractItemModel::flags(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||||
|
int role) const
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||||
|
return m_rootItem->data(section);
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
TreeItem *parentItem;
|
||||||
|
|
||||||
|
if (!parent.isValid())
|
||||||
|
parentItem = m_rootItem;
|
||||||
|
else
|
||||||
|
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||||
|
|
||||||
|
TreeItem *childItem = parentItem->child(row);
|
||||||
|
if (childItem)
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
else
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
TreeItem *parentItem = childItem->parentItem();
|
||||||
|
|
||||||
|
if (parentItem == m_rootItem)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
TreeItem *parentItem;
|
||||||
|
if (parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!parent.isValid())
|
||||||
|
parentItem = m_rootItem;
|
||||||
|
else
|
||||||
|
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||||
|
|
||||||
|
return parentItem->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TreeModel::setupModelData(const QByteArray &lines, TreeItem *parent)
|
||||||
|
{
|
||||||
|
QList<TreeItem*> parents;
|
||||||
|
QList<int> indentations;
|
||||||
|
|
||||||
|
indentations << 0;
|
||||||
|
|
||||||
|
typedef std::map<profiler::timestamp_t, profiler::SerilizedBlock> blocks_map_t;
|
||||||
|
typedef std::map<size_t, blocks_map_t> thread_map_t;
|
||||||
|
thread_map_t blocksList;
|
||||||
|
QByteArray array(lines);
|
||||||
|
QDataStream io(&array,QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while(!io.atEnd()){
|
||||||
|
uint16_t sz = 0;
|
||||||
|
io.readRawData((char*)&sz,sizeof(sz));
|
||||||
|
char* data = new char[sz];
|
||||||
|
io.readRawData(data,sz);
|
||||||
|
profiler::BaseBlockData* baseData = (profiler::BaseBlockData*)data;
|
||||||
|
blocksList[baseData->getThreadId()].emplace(
|
||||||
|
baseData->getBegin(),
|
||||||
|
std::move(profiler::SerilizedBlock(sz, data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& threads_list : blocksList){
|
||||||
|
|
||||||
|
std::list<const profiler::BaseBlockData *> parents_blocks;
|
||||||
|
parents.clear();
|
||||||
|
parents << parent;
|
||||||
|
|
||||||
|
for (auto& i : threads_list.second){
|
||||||
|
QList<QVariant> columnData;
|
||||||
|
const profiler::BaseBlockData * _block = i.second.block();
|
||||||
|
|
||||||
|
profiler::timestamp_t _end = _block->getEnd();
|
||||||
|
profiler::timestamp_t _begin = _block->getBegin();
|
||||||
|
|
||||||
|
columnData << i.second.getBlockName();
|
||||||
|
columnData << QVariant::fromValue(_block->duration());
|
||||||
|
columnData << QVariant::fromValue(_block->getThreadId());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(parents_blocks.empty()){
|
||||||
|
parents_blocks.push_back(_block);
|
||||||
|
parents << parents.last();
|
||||||
|
}else{
|
||||||
|
|
||||||
|
auto& last_block_in_stack = parents_blocks.back();
|
||||||
|
auto last_block_end = last_block_in_stack->getEnd();
|
||||||
|
|
||||||
|
if(_begin >= last_block_end){
|
||||||
|
parents_blocks.pop_back();
|
||||||
|
parents.pop_back();
|
||||||
|
|
||||||
|
for(std::list<const profiler::BaseBlockData *>::reverse_iterator it = parents_blocks.rbegin(); it != parents_blocks.rend();){
|
||||||
|
last_block_end = (*it)->getEnd();
|
||||||
|
|
||||||
|
if(_end <= last_block_end){
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
|
parents_blocks.erase( std::next(it).base() );
|
||||||
|
parents.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parents_blocks.push_back(_block);
|
||||||
|
if(parents.size() > 1){
|
||||||
|
parents << parents.last()->child(parents.last()->childCount()-1);
|
||||||
|
}else{
|
||||||
|
parents << parents.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}else if(_end <= last_block_end){
|
||||||
|
//child
|
||||||
|
|
||||||
|
parents_blocks.push_back(_block);
|
||||||
|
if(parents.size() > 1){
|
||||||
|
parents << parents.last()->child(parents.last()->childCount()-1);
|
||||||
|
}else{
|
||||||
|
parents << parents.last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
columnData << QVariant::fromValue(_block->getBegin() - _begin);
|
||||||
|
|
||||||
|
if(_block->getType() == profiler::BLOCK_TYPE_BLOCK){
|
||||||
|
parents.last()->appendChild(new TreeItem(columnData, parents.last()));
|
||||||
|
}else{
|
||||||
|
//parents.last()->appendChild(new TreeItem(columnData, parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
while (number < lines.count()) {
|
||||||
|
int position = 0;
|
||||||
|
while (position < lines[number].length()) {
|
||||||
|
if (lines[number].at(position) != ' ')
|
||||||
|
break;
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString lineData = lines[number].mid(position).trimmed();
|
||||||
|
|
||||||
|
if (!lineData.isEmpty()) {
|
||||||
|
// Read the column data from the rest of the line.
|
||||||
|
QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
|
||||||
|
QList<QVariant> columnData;
|
||||||
|
for (int column = 0; column < columnStrings.count(); ++column)
|
||||||
|
columnData << columnStrings[column];
|
||||||
|
|
||||||
|
if (position > indentations.last()) {
|
||||||
|
// The last child of the current parent is now the new parent
|
||||||
|
// unless the current parent has no children.
|
||||||
|
|
||||||
|
if (parents.last()->childCount() > 0) {
|
||||||
|
parents << parents.last()->child(parents.last()->childCount()-1);
|
||||||
|
indentations << position;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (position < indentations.last() && parents.count() > 0) {
|
||||||
|
parents.pop_back();
|
||||||
|
indentations.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append a new item to the current parent's list of children.
|
||||||
|
parents.last()->appendChild(new TreeItem(columnData, parents.last()));
|
||||||
|
}
|
||||||
|
|
||||||
|
++number;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
34
profiler_gui/treemodel.h
Normal file
34
profiler_gui/treemodel.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef TREEMODEL_H
|
||||||
|
#define TREEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
class TreeItem;
|
||||||
|
|
||||||
|
class TreeModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TreeModel(const QByteArray &data, QObject *parent = 0);
|
||||||
|
~TreeModel();
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
|
int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||||
|
QModelIndex index(int row, int column,
|
||||||
|
const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupModelData(const QByteArray &lines, TreeItem *parent);
|
||||||
|
|
||||||
|
TreeItem *m_rootItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TREEMODEL_H
|
@ -9,14 +9,33 @@ void loadingResources(){
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void prepareMath(){
|
void prepareMath(){
|
||||||
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
|
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void calcIntersect(){
|
||||||
|
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(700));
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcPhys(){
|
||||||
|
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
|
||||||
|
calcIntersect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcBrain(){
|
||||||
|
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(300));
|
||||||
|
}
|
||||||
|
|
||||||
void calculateBehavior(){
|
void calculateBehavior(){
|
||||||
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Lightblue);
|
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Lightblue);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||||
|
calcPhys();
|
||||||
|
calcBrain();
|
||||||
}
|
}
|
||||||
|
|
||||||
void modellingStep(){
|
void modellingStep(){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user