0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-26 16:11:02 +08:00

(profiler_gui) Memory consumption optimization + File reading speed-up.

This commit is contained in:
Victor Zarubkin 2016-08-30 22:51:18 +03:00
parent 245bc6c386
commit 9560c5b5cf
15 changed files with 581 additions and 519 deletions

View File

@ -72,23 +72,21 @@ namespace profiler {
public:
typedef ::std::vector<BlocksTree> children_t;
typedef ::std::vector<This> blocks_t;
typedef ::std::vector<::profiler::block_index_t> children_t;
children_t children; ///< List of children blocks. May be empty.
::profiler::SerializedBlock* node; ///< Pointer to serilized data (type, name, begin, end etc.)
::profiler::BlockStatistics* per_parent_stats; ///< Pointer to statistics for this block within the parent (may be nullptr for top-level blocks)
::profiler::BlockStatistics* per_frame_stats; ///< Pointer to statistics for this block within the frame (may be nullptr for top-level blocks)
::profiler::BlockStatistics* per_thread_stats; ///< Pointer to statistics for this block within the bounds of all frames per current thread
::profiler::block_index_t block_index; ///< Index of this block
unsigned short depth; ///< Maximum number of sublevels (maximum children depth)
uint16_t depth; ///< Maximum number of sublevels (maximum children depth)
BlocksTree()
: node(nullptr)
, per_parent_stats(nullptr)
, per_frame_stats(nullptr)
, per_thread_stats(nullptr)
, block_index(0)
, depth(0)
{
@ -143,33 +141,20 @@ namespace profiler {
void makeMove(This&& that)
{
//if (node && node != that.node)
//{
// delete node;
//}
if (per_thread_stats != that.per_thread_stats)
{
release_stats(per_thread_stats);
}
if (per_parent_stats != that.per_parent_stats)
{
release_stats(per_parent_stats);
}
if (per_frame_stats != that.per_frame_stats)
{
release_stats(per_frame_stats);
}
children = ::std::move(that.children);
node = that.node;
per_parent_stats = that.per_parent_stats;
per_frame_stats = that.per_frame_stats;
per_thread_stats = that.per_thread_stats;
block_index = that.block_index;
depth = that.depth;
that.node = nullptr;
@ -188,29 +173,31 @@ namespace profiler {
public:
BlocksTree tree;
BlocksTree::children_t children;
const char* thread_name;
::profiler::thread_id_t thread_id;
uint16_t depth;
BlocksTreeRoot() : thread_name(""), thread_id(0)
BlocksTreeRoot() : thread_name(""), thread_id(0), depth(0)
{
}
BlocksTreeRoot(This&& that) : tree(::std::move(that.tree)), thread_name(that.thread_name), thread_id(that.thread_id)
BlocksTreeRoot(This&& that) : children(::std::move(that.children)), thread_name(that.thread_name), thread_id(that.thread_id), depth(that.depth)
{
}
This& operator = (This&& that)
{
tree = ::std::move(that.tree);
children = ::std::move(that.children);
thread_name = that.thread_name;
thread_id = that.thread_id;
depth = that.depth;
return *this;
}
bool operator < (const This& other) const
{
return tree < other.tree;
return thread_id < other.thread_id;
}
private:
@ -220,6 +207,7 @@ namespace profiler {
}; // END of class BlocksTreeRoot.
typedef ::profiler::BlocksTree::blocks_t blocks_t;
typedef ::std::map<::profiler::thread_id_t, ::profiler::BlocksTreeRoot> thread_blocks_tree_t;
//////////////////////////////////////////////////////////////////////////
@ -283,11 +271,21 @@ namespace profiler {
} // END of namespace profiler.
extern "C" unsigned int PROFILER_API fillTreesFromFile(::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics = false);
extern "C" ::profiler::block_index_t PROFILER_API fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics = false);
inline unsigned int fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics = false) {
inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics = false)
{
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, threaded_trees, gather_statistics);
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, gather_statistics);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -153,7 +153,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
// Search for first visible top-level item
auto& level0 = m_levels.front();
auto first = ::std::lower_bound(level0.begin(), level0.end(), sceneLeft, [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
auto first = ::std::lower_bound(level0.begin(), level0.end(), sceneLeft, [](const ::profiler_gui::EasyBlockItem& _item, qreal _value)
{
return _item.left() < _value;
});
@ -183,7 +183,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setTransform(QTransform::fromTranslate(dx - offset * currentScale, -y()), true);
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders)
if (EASY_GLOBALS.draw_graphics_items_borders)
{
previousPenStyle = Qt::SolidLine;
_painter->setPen(BORDERS_COLOR);
@ -194,8 +194,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max<decltype(::profiler_gui::ProfBlockItem::children_begin)>();
auto const skip_children = [this, &levelsNumber](short next_level, decltype(::profiler_gui::ProfBlockItem::children_begin) children_begin)
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max<decltype(::profiler_gui::EasyBlockItem::children_begin)>();
auto const skip_children = [this, &levelsNumber](short next_level, decltype(::profiler_gui::EasyBlockItem::children_begin) children_begin)
{
// Mark that we would not paint children of current item
if (next_level < levelsNumber && children_begin != MAX_CHILD_INDEX)
@ -243,8 +243,9 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
continue;
}
const auto& itemBlock = easyBlock(item.block);
int h = 0, flags = 0;
if (w < 20 || !::profiler_gui::EASY_GLOBALS.gui_blocks[item.block->block_index].expanded)
if (w < 20 || !itemBlock.expanded)
{
// Items which width is less than 20 will be painted as big rectangles which are hiding it's children
@ -255,7 +256,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
h -= dh;
bool changepen = false;
if (item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
if (item.block == EASY_GLOBALS.selected_block)
{
selectedItemsWasPainted = true;
changepen = true;
@ -281,7 +282,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders)
if (EASY_GLOBALS.draw_graphics_items_borders)
{
//if (w < 2)
//{
@ -349,7 +350,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
m_levels[next_level][item.children_begin].state = BLOCK_ITEM_DO_PAINT;
}
if (item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
if (item.block == EASY_GLOBALS.selected_block)
{
selectedItemsWasPainted = true;
QPen pen(Qt::SolidLine);
@ -374,7 +375,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders && (previousPenStyle != Qt::SolidLine || colorChange))
if (EASY_GLOBALS.draw_graphics_items_borders && (previousPenStyle != Qt::SolidLine || colorChange))
{
// Restore pen for item which is wide enough to paint borders
previousPenStyle = Qt::SolidLine;
@ -422,7 +423,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setPen(textColor);
// drawing text
auto name = *item.block->node->name() != 0 ? item.block->node->name() : ::profiler_gui::EASY_GLOBALS.descriptors[item.block->node->id()]->name();
auto name = *itemBlock.tree.node->name() != 0 ? itemBlock.tree.node->name() : easyDescriptor(itemBlock.tree.node->id()).name();
_painter->drawText(rect, flags, ::profiler_gui::toUnicode(name));
// restore previous pen color
@ -434,9 +435,9 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
}
if (!selectedItemsWasPainted && ::profiler_gui::EASY_GLOBALS.selected_block < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
if (!selectedItemsWasPainted && EASY_GLOBALS.selected_block < EASY_GLOBALS.gui_blocks.size())
{
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[::profiler_gui::EASY_GLOBALS.selected_block];
const auto& guiblock = EASY_GLOBALS.gui_blocks[EASY_GLOBALS.selected_block];
if (guiblock.graphics_item == m_index)
{
const auto& item = m_levels[guiblock.graphics_item_level][guiblock.graphics_item_index];
@ -482,7 +483,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setPen(textColor);
// drawing text
auto name = *item.block->node->name() != 0 ? item.block->node->name() : ::profiler_gui::EASY_GLOBALS.descriptors[item.block->node->id()]->name();
const auto& itemBlock = easyBlock(item.block);
auto name = *itemBlock.tree.node->name() != 0 ? itemBlock.tree.node->name() : easyDescriptor(itemBlock.tree.node->id()).name();
_painter->drawText(rect, Qt::AlignCenter, ::profiler_gui::toUnicode(name));
// END Draw text~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
@ -511,7 +513,7 @@ void EasyGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tree
// Search for first visible top-level item
auto& level0 = m_levels.front();
auto first = ::std::lower_bound(level0.begin(), level0.end(), _left, [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
auto first = ::std::lower_bound(level0.begin(), level0.end(), _left, [](const ::profiler_gui::EasyBlockItem& _item, qreal _value)
{
return _item.left() < _value;
});
@ -552,7 +554,7 @@ void EasyGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tree
//////////////////////////////////////////////////////////////////////////
const ::profiler_gui::ProfBlockItem* EasyGraphicsItem::intersect(const QPointF& _pos) const
const ::profiler_gui::EasyBlockItem* EasyGraphicsItem::intersect(const QPointF& _pos) const
{
if (m_levels.empty() || m_levels.front().empty())
{
@ -588,7 +590,7 @@ const ::profiler_gui::ProfBlockItem* EasyGraphicsItem::intersect(const QPointF&
const auto& level = m_levels[i];
// Search for first visible item
auto first = ::std::lower_bound(level.begin() + firstItem, level.begin() + lastItem, _pos.x(), [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
auto first = ::std::lower_bound(level.begin() + firstItem, level.begin() + lastItem, _pos.x(), [](const ::profiler_gui::EasyBlockItem& _item, qreal _value)
{
return _item.left() < _value;
});
@ -620,7 +622,7 @@ const ::profiler_gui::ProfBlockItem* EasyGraphicsItem::intersect(const QPointF&
}
const auto w = item.width() * currentScale;
if (i == levelIndex || w < 20 || !::profiler_gui::EASY_GLOBALS.gui_blocks[item.block->block_index].expanded)
if (i == levelIndex || w < 20 || !easyBlock(item.block).expanded)
{
return &item;
}
@ -725,12 +727,12 @@ const EasyGraphicsItem::Children& EasyGraphicsItem::items(unsigned char _level)
return m_levels[_level];
}
const ::profiler_gui::ProfBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index) const
const ::profiler_gui::EasyBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index) const
{
return m_levels[_level][_index];
}
::profiler_gui::ProfBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index)
::profiler_gui::EasyBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index)
{
return m_levels[_level][_index];
}
@ -862,7 +864,7 @@ void EasyChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
_painter->setFont(CHRONOMETER_FONT);
int textFlags = 0;
switch (::profiler_gui::EASY_GLOBALS.chrono_text_position)
switch (EASY_GLOBALS.chrono_text_position)
{
case ::profiler_gui::ChronoTextPosition_Top:
textFlags = Qt::AlignTop | Qt::AlignHCenter;
@ -1001,7 +1003,7 @@ void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte
if (top > h || bottom < 0)
continue;
if (item->threadId() == ::profiler_gui::EASY_GLOBALS.selected_thread)
if (item->threadId() == EASY_GLOBALS.selected_thread)
_painter->setBrush(QBrush(QColor::fromRgb(::profiler_gui::SELECTED_THREAD_BACKGROUND)));
else
_painter->setBrush(brushes[i & 1]);
@ -1291,8 +1293,8 @@ void EasyGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
if (longestItem != nullptr)
{
m_pScrollbar->setMinimapFrom(0, longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
emit::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(0);
EASY_GLOBALS.selected_thread = 0;
emitEASY_GLOBALS.events.selectedThreadChanged(0);
}
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
@ -1359,13 +1361,13 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
// Calculating start and end time
::profiler::timestamp_t finish = 0;
const ::profiler::BlocksTree* longestTree = nullptr;
::profiler::thread_id_t longestTree = 0;
const EasyGraphicsItem* longestItem = nullptr;
for (const auto& threadTree : _blocksTree)
{
const auto& tree = threadTree.second.tree;
const auto timestart = tree.children.front().node->begin();
const auto timefinish = tree.children.back().node->end();
const auto& tree = threadTree.second.children;
const auto timestart = blocksTree(tree.front()).node->begin();
const auto timefinish = blocksTree(tree.back()).node->end();
if (m_beginTime > timestart)
{
@ -1375,7 +1377,7 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
if (finish < timefinish)
{
finish = timefinish;
longestTree = &tree;
longestTree = threadTree.first;
}
}
@ -1391,13 +1393,13 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
}
// fill scene with new items
const auto& tree = threadTree.second.tree;
qreal h = 0, x = time2position(tree.children.front().node->begin());
const auto& tree = threadTree.second.children;
qreal h = 0, x = time2position(blocksTree(tree.front()).node->begin());
auto item = new EasyGraphicsItem(static_cast<unsigned char>(m_items.size()), &threadTree.second);
item->setLevels(tree.depth);
item->setLevels(threadTree.second.depth);
item->setPos(0, y);
const auto children_duration = setTree(item, tree.children, h, y, 0);
const auto children_duration = setTree(item, tree, h, y, 0);
item->setBoundingRect(0, 0, children_duration + x, h);
m_items.push_back(item);
@ -1405,7 +1407,7 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
y += h + THREADS_ROW_SPACING;
if (longestTree == &tree)
if (longestTree == threadTree.first)
{
longestItem = item;
}
@ -1424,8 +1426,8 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
if (longestItem != nullptr)
{
m_pScrollbar->setMinimapFrom(longestItem->threadId(), longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = longestItem->threadId();
emit::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(longestItem->threadId());
EASY_GLOBALS.selected_thread = longestItem->threadId();
emit EASY_GLOBALS.events.selectedThreadChanged(longestItem->threadId());
}
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
@ -1466,8 +1468,11 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
bool warned = false;
qreal total_duration = 0, prev_end = 0, maxh = 0;
qreal start_time = -1;
for (const auto& child : _children)
for (auto child_index : _children)
{
auto& gui_block = easyBlock(child_index);
const auto& child = gui_block.tree;
auto xbegin = time2position(child.node->begin());
if (start_time < 0)
{
@ -1491,7 +1496,6 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
auto i = _item->addItem(level);
auto& b = _item->getItem(level, i);
auto& gui_block = ::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index];
gui_block.graphics_item = _item->index();
gui_block.graphics_item_level = level;
gui_block.graphics_item_index = i;
@ -1528,8 +1532,8 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
maxh = h;
}
const auto color = ::profiler_gui::EASY_GLOBALS.descriptors[child.node->id()]->color();
b.block = &child;
const auto color = EASY_GLOBALS.descriptors[child.node->id()]->color();
b.block = child_index;// &child;
b.color = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
b.setPos(xbegin, duration);
b.totalHeight = GRAPHICS_ROW_SIZE + h;
@ -1570,8 +1574,8 @@ void EasyGraphicsView::setScrollbar(EasyGraphicsScrollbar* _scrollbar)
connect(m_pScrollbar, &EasyGraphicsScrollbar::wheeled, this, &This::onGraphicsScrollbarWheel);
}
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
emit ::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(0);
EASY_GLOBALS.selected_thread = 0;
emit EASY_GLOBALS.events.selectedThreadChanged(0);
}
//////////////////////////////////////////////////////////////////////////
@ -1646,7 +1650,7 @@ void EasyGraphicsView::onGraphicsScrollbarWheel(qreal _mouseX, int _wheelDelta)
{
for (auto item : m_items)
{
if (item->threadId() == ::profiler_gui::EASY_GLOBALS.selected_thread)
if (item->threadId() == EASY_GLOBALS.selected_thread)
{
m_bUpdatingRect = true;
auto vbar = verticalScrollBar();
@ -1779,8 +1783,8 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
}
}
const ::profiler_gui::ProfBlockItem* selectedBlock = nullptr;
const auto previouslySelectedBlock = ::profiler_gui::EASY_GLOBALS.selected_block;
const ::profiler_gui::EasyBlockItem* selectedBlock = nullptr;
const auto previouslySelectedBlock = EASY_GLOBALS.selected_block;
if (m_mouseButtons & Qt::LeftButton)
{
bool clicked = false;
@ -1813,15 +1817,15 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
{
changedSelectedItem = true;
selectedBlock = block;
::profiler_gui::EASY_GLOBALS.selected_block = block->block->block_index;
EASY_GLOBALS.selected_block = block->block;
break;
}
}
if (!changedSelectedItem && ::profiler_gui::EASY_GLOBALS.selected_block != ::profiler_gui::numeric_max(::profiler_gui::EASY_GLOBALS.selected_block))
if (!changedSelectedItem && EASY_GLOBALS.selected_block != ::profiler_gui::numeric_max(EASY_GLOBALS.selected_block))
{
changedSelectedItem = true;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::profiler_gui::set_max(EASY_GLOBALS.selected_block);
}
}
}
@ -1841,12 +1845,12 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
if (changedSelectedItem)
{
m_bUpdatingRect = true;
if (selectedBlock != nullptr && previouslySelectedBlock == ::profiler_gui::EASY_GLOBALS.selected_block && !selectedBlock->block->children.empty())
if (selectedBlock != nullptr && previouslySelectedBlock == EASY_GLOBALS.selected_block && !blocksTree(selectedBlock->block).children.empty())
{
::profiler_gui::EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded = !::profiler_gui::EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded = !EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded;
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(::profiler_gui::EASY_GLOBALS.selected_block);
emit EASY_GLOBALS.events.selectedBlockChanged(EASY_GLOBALS.selected_block);
m_bUpdatingRect = false;
updateScene();
@ -1998,7 +2002,7 @@ void EasyGraphicsView::initMode()
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &This::onScrollbarValueChange);
connect(&m_flickerTimer, &QTimer::timeout, this, &This::onFlickerTimeout);
auto globalSignals = &::profiler_gui::EASY_GLOBALS.events;
auto globalSignals = &EASY_GLOBALS.events;
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::itemsExpandStateChanged, this, &This::onItemsEspandStateChange);
@ -2101,11 +2105,11 @@ void EasyGraphicsView::onSelectedBlockChange(unsigned int _block_index)
{
if (!m_bUpdatingRect)
{
if (_block_index < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
if (_block_index < EASY_GLOBALS.gui_blocks.size())
{
// Scroll to item
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index];
const auto& guiblock = EASY_GLOBALS.gui_blocks[_block_index];
const auto thread_item = m_items[guiblock.graphics_item];
const auto& item = thread_item->items(guiblock.graphics_item_level)[guiblock.graphics_item_index];
@ -2180,7 +2184,7 @@ EasyThreadViewWidget::EasyThreadViewWidget(QWidget *parent, EasyGraphicsView* vi
//m_layout->addWidget(m_label);
//setLayout(m_layout);
//show();
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
}
EasyThreadViewWidget::~EasyThreadViewWidget()
@ -2191,14 +2195,14 @@ EasyThreadViewWidget::~EasyThreadViewWidget()
void EasyThreadViewWidget::onSelectedThreadChange(::profiler::thread_id_t _id)
{
/*
auto threadName = ::profiler_gui::EASY_GLOBALS.profiler_blocks[::profiler_gui::EASY_GLOBALS.selected_thread].thread_name;
auto threadName = EASY_GLOBALS.profiler_blocks[EASY_GLOBALS.selected_thread].thread_name;
if(threadName[0]!=0)
{
m_label->setText(threadName);
}
else
{
m_label->setText(QString("Thread %1").arg(::profiler_gui::EASY_GLOBALS.selected_thread));
m_label->setText(QString("Thread %1").arg(EASY_GLOBALS.selected_thread));
}
*/
QLayoutItem *ditem;

View File

@ -58,7 +58,7 @@ inline qreal microseconds2units(qreal _value)
class EasyGraphicsItem : public QGraphicsItem
{
typedef ::profiler_gui::ProfItems Children;
typedef ::profiler_gui::EasyItems Children;
typedef ::std::vector<unsigned int> DrawIndexes;
typedef ::std::vector<Children> Sublevels;
@ -118,13 +118,13 @@ public:
\param _level Index of the level
\param _index Index of required item */
const ::profiler_gui::ProfBlockItem& getItem(unsigned char _level, unsigned int _index) const;
const ::profiler_gui::EasyBlockItem& getItem(unsigned char _level, unsigned int _index) const;
/**\brief Returns reference to the item with required index on specified level.
\param _level Index of the level
\param _index Index of required item */
::profiler_gui::ProfBlockItem& getItem(unsigned char _level, unsigned int _index);
::profiler_gui::EasyBlockItem& getItem(unsigned char _level, unsigned int _index);
/** \brief Adds new item to required level.
@ -142,7 +142,7 @@ public:
\param _blocks Reference to the array of selected blocks */
void getBlocks(qreal _left, qreal _right, ::profiler_gui::TreeBlocks& _blocks) const;
const ::profiler_gui::ProfBlockItem* intersect(const QPointF& _pos) const;
const ::profiler_gui::EasyBlockItem* intersect(const QPointF& _pos) const;
private:

View File

@ -104,8 +104,8 @@ EasyTreeWidget::EasyTreeWidget(QWidget* _parent)
setHeaderItem(header);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
connect(&m_fillTimer, &QTimer::timeout, this, &This::onFillTimerTimeout);
loadSettings();
@ -163,8 +163,8 @@ void EasyTreeWidget::onFillTimerTimeout()
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
connect(this, &Parent::itemCollapsed, this, &This::onItemCollapse);
connect(this, &Parent::currentItemChanged, this, &This::onCurrentItemChange);
onSelectedThreadChange(::profiler_gui::EASY_GLOBALS.selected_thread);
onSelectedBlockChange(::profiler_gui::EASY_GLOBALS.selected_block);
onSelectedThreadChange(EASY_GLOBALS.selected_thread);
onSelectedBlockChange(EASY_GLOBALS.selected_block);
}
else
{
@ -194,7 +194,7 @@ void EasyTreeWidget::setTree(const unsigned int _blocksNumber, const ::profiler:
// {
// addTopLevelItem(item.second);
// m_roots[item.first] = item.second;
// if (item.first == ::profiler_gui::EASY_GLOBALS.selected_thread)
// if (item.first == EASY_GLOBALS.selected_thread)
// item.second->colorize(true);
// }
//}
@ -227,7 +227,7 @@ void EasyTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, ::
// {
// addTopLevelItem(item.second);
// m_roots[item.first] = item.second;
// if (item.first == ::profiler_gui::EASY_GLOBALS.selected_thread)
// if (item.first == EASY_GLOBALS.selected_thread)
// item.second->colorize(true);
// }
//}
@ -238,7 +238,7 @@ void EasyTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, ::
//connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
//connect(this, &Parent::itemCollapsed, this, &This::onItemCollapse);
//onSelectedBlockChange(::profiler_gui::EASY_GLOBALS.selected_block);
//onSelectedBlockChange(EASY_GLOBALS.selected_block);
}
//////////////////////////////////////////////////////////////////////////
@ -265,15 +265,15 @@ void EasyTreeWidget::clearSilent(bool _global)
if (!_global)
{
if (::profiler_gui::EASY_GLOBALS.collapse_items_on_tree_close) for (auto item : m_items)
if (EASY_GLOBALS.collapse_items_on_tree_close) for (auto item : m_items)
{
auto& gui_block = ::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index];
auto& gui_block = item->guiBlock();
::profiler_gui::set_max(gui_block.tree_item);
gui_block.expanded = false;
}
else for (auto item : m_items)
{
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].tree_item);
::profiler_gui::set_max(item->guiBlock().tree_item);
}
}
@ -294,7 +294,7 @@ void EasyTreeWidget::clearSilent(bool _global)
//clear();
if (!_global)
emit::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
//////////////////////////////////////////////////////////////////////////
@ -339,7 +339,7 @@ void EasyTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
action->setChecked(m_bColorRows);
connect(action, &QAction::triggered, this, &This::onColorizeRowsTriggered);
if (item != nullptr)
if (item != nullptr && item->parent() != nullptr)
{
//auto itemAction = new EasyItemAction("Show this item on scene", item->block()->block_index);
//itemAction->setToolTip("Scroll graphics scene to current item in the tree");
@ -357,16 +357,16 @@ void EasyTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
case COL_MAX_PER_PARENT:
case COL_MAX_PER_FRAME:
{
auto block = item->block();
auto& block = item->block();
auto i = ::profiler_gui::numeric_max<unsigned int>();
switch (col)
{
case COL_MIN_PER_THREAD: i = block->per_thread_stats->min_duration_block; break;
case COL_MIN_PER_PARENT: i = block->per_parent_stats->min_duration_block; break;
case COL_MIN_PER_FRAME: i = block->per_frame_stats->min_duration_block; break;
case COL_MAX_PER_THREAD: i = block->per_thread_stats->max_duration_block; break;
case COL_MAX_PER_PARENT: i = block->per_parent_stats->max_duration_block; break;
case COL_MAX_PER_FRAME: i = block->per_frame_stats->max_duration_block; break;
case COL_MIN_PER_THREAD: i = block.per_thread_stats->min_duration_block; break;
case COL_MIN_PER_PARENT: i = block.per_parent_stats->min_duration_block; break;
case COL_MIN_PER_FRAME: i = block.per_frame_stats->min_duration_block; break;
case COL_MAX_PER_THREAD: i = block.per_thread_stats->max_duration_block; break;
case COL_MAX_PER_PARENT: i = block.per_parent_stats->max_duration_block; break;
case COL_MAX_PER_FRAME: i = block.per_frame_stats->max_duration_block; break;
}
if (i != ::profiler_gui::numeric_max(i))
@ -427,8 +427,8 @@ void EasyTreeWidget::alignProgressBar()
void EasyTreeWidget::onJumpToItemClicked(unsigned int _block_index)
{
::profiler_gui::EASY_GLOBALS.selected_block = _block_index;
emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(_block_index);
EASY_GLOBALS.selected_block = _block_index;
emit EASY_GLOBALS.events.selectedBlockChanged(_block_index);
}
void EasyTreeWidget::onCollapseAllClicked(bool)
@ -439,11 +439,11 @@ void EasyTreeWidget::onCollapseAllClicked(bool)
collapseAll();
m_bSilentExpandCollapse = false;
if (::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status)
if (EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
for (auto item : m_items)
::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = false;
emit::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
item->guiBlock().expanded = false;
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
@ -456,11 +456,15 @@ void EasyTreeWidget::onExpandAllClicked(bool)
resizeColumnsToContents();
m_bSilentExpandCollapse = false;
if (::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status)
if (EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
for (auto item : m_items)
::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = !item->block()->children.empty();
emit::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
{
auto& b = item->guiBlock();
b.expanded = !b.tree.children.empty();
}
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
@ -475,7 +479,7 @@ void EasyTreeWidget::onCollapseAllChildrenClicked(bool)
current->collapseAll();
m_bSilentExpandCollapse = false;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
@ -491,7 +495,7 @@ void EasyTreeWidget::onExpandAllChildrenClicked(bool)
resizeColumnsToContents();
m_bSilentExpandCollapse = false;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
@ -499,30 +503,30 @@ void EasyTreeWidget::onExpandAllChildrenClicked(bool)
void EasyTreeWidget::onItemExpand(QTreeWidgetItem* _item)
{
if (!::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status)
if (!EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
resizeColumnsToContents();
return;
}
::profiler_gui::EASY_GLOBALS.gui_blocks[static_cast<EasyTreeWidgetItem*>(_item)->block()->block_index].expanded = true;
static_cast<EasyTreeWidgetItem*>(_item)->guiBlock().expanded = true;
if (!m_bSilentExpandCollapse)
{
resizeColumnsToContents();
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
void EasyTreeWidget::onItemCollapse(QTreeWidgetItem* _item)
{
if (!::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status)
if (!EASY_GLOBALS.bind_scene_and_tree_expand_status)
return;
::profiler_gui::EASY_GLOBALS.gui_blocks[static_cast<EasyTreeWidgetItem*>(_item)->block()->block_index].expanded = false;
static_cast<EasyTreeWidgetItem*>(_item)->guiBlock().expanded = false;
if (!m_bSilentExpandCollapse)
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
//////////////////////////////////////////////////////////////////////////
@ -530,13 +534,13 @@ void EasyTreeWidget::onItemCollapse(QTreeWidgetItem* _item)
void EasyTreeWidget::onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem*)
{
if (_item == nullptr)
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::profiler_gui::set_max(EASY_GLOBALS.selected_block);
else
::profiler_gui::EASY_GLOBALS.selected_block = static_cast<EasyTreeWidgetItem*>(_item)->block()->block_index;
EASY_GLOBALS.selected_block = static_cast<EasyTreeWidgetItem*>(_item)->block_index();
disconnect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(::profiler_gui::EASY_GLOBALS.selected_block);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
disconnect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
emit EASY_GLOBALS.events.selectedBlockChanged(EASY_GLOBALS.selected_block);
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
}
//////////////////////////////////////////////////////////////////////////
@ -581,9 +585,9 @@ void EasyTreeWidget::onSelectedBlockChange(unsigned int _block_index)
EasyTreeWidgetItem* item = nullptr;
if (_block_index < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
if (_block_index < EASY_GLOBALS.gui_blocks.size())
{
const auto i = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index].tree_item;
const auto i = easyBlock(_block_index).tree_item;
if (i < m_items.size())
item = m_items[i];
}
@ -592,19 +596,19 @@ void EasyTreeWidget::onSelectedBlockChange(unsigned int _block_index)
{
//const QSignalBlocker b(this);
if (::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status)
if (EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
m_bSilentExpandCollapse = true;
setCurrentItem(item);
scrollToItem(item, QAbstractItemView::PositionAtCenter);
if (::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded)
if (item->guiBlock().expanded)
expandItem(item);
else
collapseItem(item);
resizeColumnsToContents();
m_bSilentExpandCollapse = false;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
else
{

View File

@ -105,14 +105,15 @@ inline QRgb fromProfilerRgb(unsigned int _red, unsigned int _green, unsigned int
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
struct ProfBlockItem final
struct EasyBlockItem final
{
const ::profiler::BlocksTree* block; ///< Pointer to profiler block
//const ::profiler::BlocksTree* block; ///< Pointer to profiler block
qreal x; ///< x coordinate of the item (this is made qreal=double to avoid mistakes on very wide scene)
float w; ///< Width of the item
QRgb color; ///< Background color of the item
unsigned int children_begin; ///< Index of first child item on the next sublevel
unsigned short totalHeight; ///< Total height of the item including heights of all it's children
::profiler::block_index_t block; ///< Index of profiler block
uint32_t children_begin; ///< Index of first child item on the next sublevel
uint16_t totalHeight; ///< Total height of the item including heights of all it's children
char state; ///< 0 = no change, 1 = paint, -1 = do not paint
// Possible optimizations:
@ -125,31 +126,58 @@ struct ProfBlockItem final
inline qreal right() const { return x + w; }
inline float width() const { return w; }
}; // END of struct ProfBlockItem.
#pragma pack(pop)
}; // END of struct EasyBlockItem.
typedef ::std::vector<ProfBlockItem> ProfItems;
//////////////////////////////////////////////////////////////////////////
struct ProfSelectedBlock final
struct EasyBlock final
{
const ::profiler::BlocksTreeRoot* root;
const ::profiler::BlocksTree* tree;
::profiler::BlocksTree tree;
uint32_t tree_item;
uint32_t graphics_item_index;
uint8_t graphics_item_level;
uint8_t graphics_item;
bool expanded;
ProfSelectedBlock() : root(nullptr), tree(nullptr)
EasyBlock() = default;
EasyBlock(EasyBlock&& that)
: tree(::std::move(tree))
, tree_item(that.tree_item)
, graphics_item_index(that.graphics_item_index)
, graphics_item_level(that.graphics_item_level)
, graphics_item(that.graphics_item)
, expanded(that.expanded)
{
}
ProfSelectedBlock(const ::profiler::BlocksTreeRoot* _root, const ::profiler::BlocksTree* _tree)
private:
EasyBlock(const EasyBlock&) = delete;
};
#pragma pack(pop)
typedef ::std::vector<EasyBlockItem> EasyItems;
typedef ::std::vector<EasyBlock> EasyBlocks;
//////////////////////////////////////////////////////////////////////////
struct EasySelectedBlock final
{
const ::profiler::BlocksTreeRoot* root;
::profiler::block_index_t tree;
EasySelectedBlock() : root(nullptr), tree(0xffffffff)
{
}
EasySelectedBlock(const ::profiler::BlocksTreeRoot* _root, const ::profiler::block_index_t _tree)
: root(_root)
, tree(_tree)
{
}
}; // END of struct ProfSelectedBlock.
}; // END of struct EasySelectedBlock.
typedef ::std::vector<ProfSelectedBlock> TreeBlocks;
typedef ::std::vector<EasySelectedBlock> TreeBlocks;
//////////////////////////////////////////////////////////////////////////

View File

@ -42,19 +42,6 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
struct EasyBlock final
{
unsigned int tree_item;
unsigned int graphics_item_index;
unsigned char graphics_item_level;
unsigned char graphics_item;
bool expanded;
};
#pragma pack(pop)
typedef ::std::vector<EasyBlock> EasyBlocks;
template <class T>
inline auto toUnicode(const T& _inputString) -> decltype(QTextCodec::codecForLocale()->toUnicode(_inputString))
{
@ -97,13 +84,26 @@ namespace profiler_gui {
}; // END of struct EasyGlobals.
#ifndef IGNORE_GLOBALS_DECLARATION
static EasyGlobals& EASY_GLOBALS = EasyGlobals::instance();
#endif
//////////////////////////////////////////////////////////////////////////
} // END of namespace profiler_gui.
#ifndef IGNORE_GLOBALS_DECLARATION
static ::profiler_gui::EasyGlobals& EASY_GLOBALS = ::profiler_gui::EasyGlobals::instance();
inline ::profiler_gui::EasyBlock& easyBlock(::profiler::block_index_t i) {
return EASY_GLOBALS.gui_blocks[i];
}
inline ::profiler::SerializedBlockDescriptor& easyDescriptor(::profiler::block_id_t i) {
return *EASY_GLOBALS.descriptors[i];
}
inline ::profiler::BlocksTree& blocksTree(::profiler::block_index_t i) {
return easyBlock(i).tree;
}
#endif
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

View File

@ -238,7 +238,7 @@ void EasyMinimapItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
m_boundingRect.setRect(x, y, w, h);
}
void EasyMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
void EasyMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items)
{
m_pSource = _items;
m_threadId = _thread_id;
@ -428,7 +428,7 @@ void EasyGraphicsScrollbar::hideChrono()
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsScrollbar::setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
void EasyGraphicsScrollbar::setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items)
{
m_minimap->setSource(_thread_id, _items);
m_slider->setVisible(m_minimap->isVisible());
@ -493,14 +493,14 @@ void EasyGraphicsScrollbar::resizeEvent(QResizeEvent* _event)
void EasyGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
{
if (::profiler_gui::EASY_GLOBALS.profiler_blocks.empty())
if (EASY_GLOBALS.profiler_blocks.empty())
{
return;
}
QMenu menu;
for (const auto& it : ::profiler_gui::EASY_GLOBALS.profiler_blocks)
for (const auto& it : EASY_GLOBALS.profiler_blocks)
{
QString label;
if (it.second.thread_name && it.second.thread_name[0] != 0)
@ -514,7 +514,7 @@ void EasyGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
auto action = new EasyIdAction(label, it.first);
action->setCheckable(true);
action->setChecked(it.first == ::profiler_gui::EASY_GLOBALS.selected_thread);
action->setChecked(it.first == EASY_GLOBALS.selected_thread);
connect(action, &EasyIdAction::clicked, this, &This::onThreadActionClicked);
menu.addAction(action);
@ -530,8 +530,8 @@ void EasyGraphicsScrollbar::onThreadActionClicked(::profiler::thread_id_t _id)
{
if (_id != m_minimap->threadId())
{
::profiler_gui::EASY_GLOBALS.selected_thread = _id;
emit ::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(_id);
EASY_GLOBALS.selected_thread = _id;
emit EASY_GLOBALS.events.selectedThreadChanged(_id);
}
}

View File

@ -66,7 +66,7 @@ class EasyMinimapItem : public QGraphicsItem
QRectF m_boundingRect;
qreal m_maxDuration;
qreal m_minDuration;
const ::profiler_gui::ProfItems* m_pSource;
const ::profiler_gui::EasyItems* m_pSource;
::profiler::thread_id_t m_threadId;
public:
@ -88,7 +88,7 @@ public:
void setBoundingRect(const QRectF& _rect);
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items);
void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items);
}; // END of class EasyMinimapItem.
@ -190,9 +190,9 @@ public:
void showChrono();
void hideChrono();
void setMinimapFrom(::profiler::thread_id_t _thread_id, const::profiler_gui::ProfItems* _items);
void setMinimapFrom(::profiler::thread_id_t _thread_id, const::profiler_gui::EasyItems* _items);
inline void setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems& _items)
inline void setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems& _items)
{
setMinimapFrom(_thread_id, &_items);
}

View File

@ -100,22 +100,22 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi
menu->addSeparator();
action = menu->addAction("Draw items' borders");
action->setCheckable(true);
action->setChecked(::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders);
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
connect(action, &QAction::triggered, this, &This::onDrawBordersChanged);
action = menu->addAction("Collapse items on tree reset");
action->setCheckable(true);
action->setChecked(::profiler_gui::EASY_GLOBALS.collapse_items_on_tree_close);
action->setChecked(EASY_GLOBALS.collapse_items_on_tree_close);
connect(action, &QAction::triggered, this, &This::onCollapseItemsAfterCloseChanged);
action = menu->addAction("Expand all on file open");
action->setCheckable(true);
action->setChecked(::profiler_gui::EASY_GLOBALS.all_items_expanded_by_default);
action->setChecked(EASY_GLOBALS.all_items_expanded_by_default);
connect(action, &QAction::triggered, this, &This::onAllItemsExpandedByDefaultChange);
action = menu->addAction("Bind scene and tree expand");
action->setCheckable(true);
action->setChecked(::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status);
action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange);
menu->addSeparator();
@ -126,7 +126,7 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi
action = new QAction("At top", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Top));
if (::profiler_gui::EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
@ -134,7 +134,7 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi
action = new QAction("At center", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Center));
if (::profiler_gui::EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
@ -142,7 +142,7 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi
action = new QAction("At bottom", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Bottom));
if (::profiler_gui::EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
@ -250,39 +250,39 @@ void EasyMainWindow::onEncodingChanged(bool)
void EasyMainWindow::onChronoTextPosChanged(bool)
{
auto _sender = qobject_cast<QAction*>(sender());
::profiler_gui::EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(_sender->data().toInt());
emit ::profiler_gui::EASY_GLOBALS.events.chronoPositionChanged();
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(_sender->data().toInt());
emit EASY_GLOBALS.events.chronoPositionChanged();
}
void EasyMainWindow::onDrawBordersChanged(bool _checked)
{
::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders = _checked;
emit ::profiler_gui::EASY_GLOBALS.events.drawBordersChanged();
EASY_GLOBALS.draw_graphics_items_borders = _checked;
emit EASY_GLOBALS.events.drawBordersChanged();
}
void EasyMainWindow::onCollapseItemsAfterCloseChanged(bool _checked)
{
::profiler_gui::EASY_GLOBALS.collapse_items_on_tree_close = _checked;
EASY_GLOBALS.collapse_items_on_tree_close = _checked;
}
void EasyMainWindow::onAllItemsExpandedByDefaultChange(bool _checked)
{
::profiler_gui::EASY_GLOBALS.all_items_expanded_by_default = _checked;
EASY_GLOBALS.all_items_expanded_by_default = _checked;
}
void EasyMainWindow::onBindExpandStatusChange(bool _checked)
{
::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status = _checked;
EASY_GLOBALS.bind_scene_and_tree_expand_status = _checked;
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::onExpandAllClicked(bool)
{
for (auto& block : ::profiler_gui::EASY_GLOBALS.gui_blocks)
for (auto& block : EASY_GLOBALS.gui_blocks)
block.expanded = true;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
auto tree = static_cast<EasyTreeWidget*>(m_treeWidget->widget());
const QSignalBlocker b(tree);
@ -291,10 +291,10 @@ void EasyMainWindow::onExpandAllClicked(bool)
void EasyMainWindow::onCollapseAllClicked(bool)
{
for (auto& block : ::profiler_gui::EASY_GLOBALS.gui_blocks)
for (auto& block : EASY_GLOBALS.gui_blocks)
block.expanded = false;
emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged();
emit EASY_GLOBALS.events.itemsExpandStateChanged();
auto tree = static_cast<EasyTreeWidget*>(m_treeWidget->widget());
const QSignalBlocker b(tree);
@ -326,32 +326,32 @@ void EasyMainWindow::loadSettings()
auto val = settings.value("chrono_text_position");
if (!val.isNull())
{
::profiler_gui::EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(val.toInt());
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(val.toInt());
}
auto flag = settings.value("draw_graphics_items_borders");
if (!flag.isNull())
{
::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders = flag.toBool();
EASY_GLOBALS.draw_graphics_items_borders = flag.toBool();
}
flag = settings.value("collapse_items_on_tree_close");
if (!flag.isNull())
{
::profiler_gui::EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool();
EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool();
}
flag = settings.value("all_items_expanded_by_default");
if (!flag.isNull())
{
::profiler_gui::EASY_GLOBALS.all_items_expanded_by_default = flag.toBool();
EASY_GLOBALS.all_items_expanded_by_default = flag.toBool();
}
flag = settings.value("bind_scene_and_tree_expand_status");
if (!flag.isNull())
{
::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool();
EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool();
}
QString encoding = settings.value("encoding", "UTF-8").toString();
@ -379,11 +379,11 @@ void EasyMainWindow::saveSettingsAndGeometry()
settings.setValue("geometry", this->saveGeometry());
settings.setValue("last_file", m_lastFile);
settings.setValue("chrono_text_position", static_cast<int>(::profiler_gui::EASY_GLOBALS.chrono_text_position));
settings.setValue("draw_graphics_items_borders", ::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders);
settings.setValue("collapse_items_on_tree_close", ::profiler_gui::EASY_GLOBALS.collapse_items_on_tree_close);
settings.setValue("all_items_expanded_by_default", ::profiler_gui::EASY_GLOBALS.all_items_expanded_by_default);
settings.setValue("bind_scene_and_tree_expand_status", ::profiler_gui::EASY_GLOBALS.bind_scene_and_tree_expand_status);
settings.setValue("chrono_text_position", static_cast<int>(EASY_GLOBALS.chrono_text_position));
settings.setValue("draw_graphics_items_borders", EASY_GLOBALS.draw_graphics_items_borders);
settings.setValue("collapse_items_on_tree_close", EASY_GLOBALS.collapse_items_on_tree_close);
settings.setValue("all_items_expanded_by_default", EASY_GLOBALS.all_items_expanded_by_default);
settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status);
settings.setValue("encoding", QTextCodec::codecForLocale()->name());
settings.endGroup();
@ -402,28 +402,34 @@ void EasyMainWindow::onFileReaderTimeout()
::profiler::SerializedData serialized_blocks, serialized_descriptors;
::profiler::descriptors_list_t descriptors;
::profiler::thread_blocks_tree_t prof_blocks;
::profiler::blocks_t blocks;
::profiler::thread_blocks_tree_t threads_map;
QString filename;
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, prof_blocks, filename);
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, filename);
if (prof_blocks.size() > 0xff)
if (threads_map.size() > 0xff)
{
qWarning() << "Warning: file " << filename << " contains " << prof_blocks.size() << " threads!";
qWarning() << "Warning: file " << filename << " contains " << threads_map.size() << " threads!";
qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed.";
}
m_lastFile = ::std::move(filename);
m_serializedBlocks = ::std::move(serialized_blocks);
m_serializedDescriptors = ::std::move(serialized_descriptors);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::profiler_gui::EASY_GLOBALS.profiler_blocks.swap(prof_blocks);
::profiler_gui::EASY_GLOBALS.descriptors.swap(descriptors);
::profiler_gui::EASY_GLOBALS.gui_blocks.resize(nblocks);
memset(::profiler_gui::EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::EasyBlock) * nblocks);
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(EASY_GLOBALS.selected_block);
EASY_GLOBALS.profiler_blocks.swap(threads_map);
EASY_GLOBALS.descriptors.swap(descriptors);
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
EASY_GLOBALS.gui_blocks.resize(nblocks);
memset(EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::EasyBlock) * nblocks);
for (decltype(nblocks) i = 0; i < nblocks; ++i) {
auto& guiblock = EASY_GLOBALS.gui_blocks[i];
guiblock.tree = ::std::move(blocks[i]);
::profiler_gui::set_max(guiblock.tree_item);
}
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(EASY_GLOBALS.profiler_blocks);
}
else
{
@ -436,7 +442,7 @@ void EasyMainWindow::onFileReaderTimeout()
m_progress->setValue(100);
//m_progress->hide();
if (::profiler_gui::EASY_GLOBALS.all_items_expanded_by_default)
if (EASY_GLOBALS.all_items_expanded_by_default)
{
onExpandAllClicked(true);
}
@ -493,7 +499,7 @@ void EasyFileReader::load(const QString& _filename)
m_filename = _filename;
m_thread = ::std::move(::std::thread([this]() {
m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors, m_descriptors, m_blocksTree, true));
m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors, m_descriptors, m_blocks, m_blocksTree, true));
m_progress.store(100);
m_bDone.store(true);
}));
@ -511,17 +517,20 @@ void EasyFileReader::interrupt()
m_serializedBlocks.clear();
m_serializedDescriptors.clear();
m_descriptors.clear();
m_blocks.clear();
m_blocksTree.clear();
}
void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::descriptors_list_t& _descriptors, ::profiler::thread_blocks_tree_t& _tree, QString& _filename)
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
QString& _filename)
{
if (done())
{
m_serializedBlocks.swap(_serializedBlocks);
m_serializedDescriptors.swap(_serializedDescriptors);
::profiler::descriptors_list_t(m_descriptors).swap(_descriptors);
::profiler::descriptors_list_t(::std::move(m_descriptors)).swap(_descriptors);
m_blocks.swap(_blocks);
m_blocksTree.swap(_tree);
m_filename.swap(_filename);
}

View File

@ -35,6 +35,7 @@ class EasyFileReader final
::profiler::SerializedData m_serializedBlocks; ///<
::profiler::SerializedData m_serializedDescriptors; ///<
::profiler::descriptors_list_t m_descriptors; ///<
::profiler::blocks_t m_blocks; ///<
::profiler::thread_blocks_tree_t m_blocksTree; ///<
QString m_filename; ///<
::std::thread m_thread; ///<
@ -55,7 +56,8 @@ public:
void load(const QString& _filename);
void interrupt();
void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::descriptors_list_t& _descriptors, ::profiler::thread_blocks_tree_t& _tree, QString& _filename);
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
QString& _filename);
}; // END of class EasyFileReader.

View File

@ -21,7 +21,7 @@
//////////////////////////////////////////////////////////////////////////
EasyTreeWidgetItem::EasyTreeWidgetItem(const ::profiler::BlocksTree* _treeBlock, Parent* _parent)
EasyTreeWidgetItem::EasyTreeWidgetItem(const ::profiler::block_index_t _treeBlock, Parent* _parent)
: Parent(_parent)
, m_block(_treeBlock)
, m_customBGColor(0)
@ -75,15 +75,25 @@ bool EasyTreeWidgetItem::operator < (const Parent& _other) const
return false;
}
const ::profiler::BlocksTree* EasyTreeWidgetItem::block() const
::profiler::block_index_t EasyTreeWidgetItem::block_index() const
{
return m_block;
}
::profiler_gui::EasyBlock& EasyTreeWidgetItem::guiBlock()
{
return easyBlock(m_block);
}
const ::profiler::BlocksTree& EasyTreeWidgetItem::block() const
{
return blocksTree(m_block);
}
::profiler::timestamp_t EasyTreeWidgetItem::duration() const
{
if (m_block->node)
return m_block->node->duration();
if (parent() != nullptr)
return block().node->duration();
return data(COL_DURATION, Qt::UserRole).toULongLong();
}
@ -173,7 +183,8 @@ void EasyTreeWidgetItem::collapseAll()
}
setExpanded(false);
::profiler_gui::EASY_GLOBALS.gui_blocks[m_block->block_index].expanded = false;
if (parent() != nullptr)
guiBlock().expanded = false;
}
void EasyTreeWidgetItem::expandAll()
@ -184,7 +195,8 @@ void EasyTreeWidgetItem::expandAll()
}
setExpanded(true);
::profiler_gui::EASY_GLOBALS.gui_blocks[m_block->block_index].expanded = true;
if (parent() != nullptr)
guiBlock().expanded = true;
}
//////////////////////////////////////////////////////////////////////////

View File

@ -75,7 +75,7 @@ class EasyTreeWidgetItem : public QTreeWidgetItem
typedef QTreeWidgetItem Parent;
typedef EasyTreeWidgetItem This;
const ::profiler::BlocksTree* m_block;
const ::profiler::block_index_t m_block;
QRgb m_customBGColor;
QRgb m_customTextColor;
@ -84,14 +84,16 @@ public:
using Parent::setBackgroundColor;
using Parent::setTextColor;
EasyTreeWidgetItem(const ::profiler::BlocksTree* _treeBlock, Parent* _parent = nullptr);
EasyTreeWidgetItem(const ::profiler::block_index_t _treeBlock = ::profiler_gui::numeric_max<decltype(m_block)>(), Parent* _parent = nullptr);
virtual ~EasyTreeWidgetItem();
bool operator < (const Parent& _other) const override;
public:
const ::profiler::BlocksTree* block() const;
::profiler::block_index_t block_index() const;
::profiler_gui::EasyBlock& guiBlock();
const ::profiler::BlocksTree& block() const;
::profiler::timestamp_t duration() const;
::profiler::timestamp_t selfDuration() const;

View File

@ -126,7 +126,7 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
::profiler::timestamp_t finishtime = 0;
for (const auto& threadTree : _blocksTree)
{
const auto node_block = threadTree.second.tree.children.front().node;
const auto node_block = blocksTree(threadTree.second.children.front()).node;
const auto startTime = node_block->begin();
const auto endTime = node_block->end();
@ -145,49 +145,49 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
if (_safelocker.interrupted())
break;
auto& block = threadTree.second.tree;
auto item = new EasyTreeWidgetItem(&block);
const auto& root = threadTree.second;
auto item = new EasyTreeWidgetItem();
if (threadTree.second.thread_name && threadTree.second.thread_name[0] != 0)
if (root.thread_name && root.thread_name[0] != 0)
{
item->setText(COL_NAME, QString("%1 Thread %2").arg(threadTree.second.thread_name).arg(threadTree.first));
item->setText(COL_NAME, QString("%1 Thread %2").arg(root.thread_name).arg(root.thread_id));
}
else
{
item->setText(COL_NAME, QString("Thread %1").arg(threadTree.first));
item->setText(COL_NAME, QString("Thread %1").arg(root.thread_id));
}
::profiler::timestamp_t duration = 0;
if (!block.children.empty())
if (!root.children.empty())
{
duration = block.children.back().node->end() - block.children.front().node->begin();
duration = blocksTree(root.children.back()).node->end() - blocksTree(root.children.front()).node->begin();
}
item->setTimeSmart(COL_DURATION, duration);
item->setBackgroundColor(::profiler_gui::SELECTED_THREAD_BACKGROUND);
item->setTextColor(::profiler_gui::SELECTED_THREAD_FOREGROUND);
_items.push_back(item);
//_items.push_back(item);
// TODO: Optimize children duration calculation (it must be calculated before setTreeInternal now)
::profiler::timestamp_t children_duration = 0;
for (const auto& child : block.children)
children_duration += child.node->duration();
for (auto i : root.children)
children_duration += blocksTree(i).node->duration();
item->setTimeSmart(COL_SELF_DURATION, children_duration);
children_duration = 0;
const auto children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, block.children, item, nullptr, item, _beginTime, finishtime + 1000000000ULL, false, children_duration, _colorizeRows);
const auto children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, root.children, item, nullptr, item, _beginTime, finishtime + 1000000000ULL, false, children_duration, _colorizeRows);
if (children_items_number > 0)
{
//total_items += children_items_number + 1;
//addTopLevelItem(item);
//m_roots[threadTree.first] = item;
_topLevelItems.emplace_back(threadTree.first, item);
_topLevelItems.emplace_back(root.thread_id, item);
}
else
{
_items.pop_back();
//_items.pop_back();
delete item;
}
@ -200,11 +200,11 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
//////////////////////////////////////////////////////////////////////////
auto calculateTotalChildrenNumber(const ::profiler::BlocksTree* _tree) -> decltype(_tree->children.size())
auto calculateTotalChildrenNumber(const ::profiler::BlocksTree& _tree) -> decltype(_tree.children.size())
{
auto children_number = _tree->children.size();
for (const auto& child : _tree->children)
children_number += calculateTotalChildrenNumber(&child);
auto children_number = _tree.children.size();
for (auto i : _tree.children)
children_number += calculateTotalChildrenNumber(blocksTree(i));
return children_number;
}
@ -213,7 +213,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
{
//size_t blocksNumber = 0;
//for (const auto& block : _blocks)
// blocksNumber += calculateTotalChildrenNumber(block.tree);
// blocksNumber += calculateTotalChildrenNumber(*block.tree);
// //blocksNumber += block.tree->total_children_number;
//m_items.reserve(blocksNumber + _blocks.size()); // blocksNumber does not include root blocks
@ -226,8 +226,9 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
if (_safelocker.interrupted())
break;
const auto startTime = block.tree->node->begin();
const auto endTime = block.tree->node->end();
auto& gui_block = easyBlock(block.tree);
const auto startTime = gui_block.tree.node->begin();
const auto endTime = gui_block.tree.node->end();
if (startTime > _right || endTime < _left)
{
_safelocker.setProgress((90 * ++i) / total);
@ -243,7 +244,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
}
else
{
thread_item = new EasyTreeWidgetItem(&block.root->tree);
thread_item = new EasyTreeWidgetItem();
if (block.root->thread_name && block.root->thread_name[0] != 0)
{
@ -254,9 +255,9 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
thread_item->setText(COL_NAME, QString("Thread %1").arg(block.root->thread_id));
}
if (!block.root->tree.children.empty())
if (!block.root->children.empty())
{
duration = block.root->tree.children.back().node->end() - block.root->tree.children.front().node->begin();
duration = blocksTree(block.root->children.back()).node->end() - blocksTree(block.root->children.front()).node->begin();
}
thread_item->setTimeSmart(COL_DURATION, duration);
@ -265,8 +266,8 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
// Calculate clean duration (sum of all children durations)
::profiler::timestamp_t children_duration = 0;
for (const auto& child : block.root->tree.children)
children_duration += child.node->duration();
for (auto i : block.root->children)
children_duration += blocksTree(i).node->duration();
thread_item->setTimeSmart(COL_SELF_DURATION, children_duration);
threadsMap.insert(::std::make_pair(block.root->thread_id, thread_item));
@ -275,7 +276,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
auto item = new EasyTreeWidgetItem(block.tree, thread_item);
duration = endTime - startTime;
auto name = *block.tree->node->name() != 0 ? block.tree->node->name() : ::profiler_gui::EASY_GLOBALS.descriptors[block.tree->node->id()]->name();
auto name = *gui_block.tree.node->name() != 0 ? gui_block.tree.node->name() : easyDescriptor(gui_block.tree.node->id()).name();
item->setText(COL_NAME, ::profiler_gui::toUnicode(name));
item->setTimeSmart(COL_DURATION, duration);
item->setTimeMs(COL_BEGIN, startTime - _beginTime);
@ -287,14 +288,14 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
item->setData(COL_PERCENT_PER_FRAME, Qt::UserRole, 0);
item->setText(COL_PERCENT_PER_FRAME, "");
if (block.tree->per_thread_stats != nullptr) // if there is per_thread_stats then there are other stats also
if (gui_block.tree.per_thread_stats != nullptr) // if there is per_thread_stats then there are other stats also
{
const auto& per_thread_stats = block.tree->per_thread_stats;
const auto& per_parent_stats = block.tree->per_parent_stats;
const auto& per_frame_stats = block.tree->per_frame_stats;
const auto& per_thread_stats = gui_block.tree.per_thread_stats;
const auto& per_parent_stats = gui_block.tree.per_parent_stats;
const auto& per_frame_stats = gui_block.tree.per_frame_stats;
if (per_thread_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_thread_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_THREAD, per_thread_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_THREAD, per_thread_stats->max_duration, "max ");
@ -310,7 +311,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
item->setText(COL_PERCENT_SUM_PER_THREAD, QString::number(percentage_per_thread));
if (per_parent_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_parent_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_PARENT, per_parent_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_PARENT, per_parent_stats->max_duration, "max ");
@ -322,7 +323,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
item->setText(COL_NCALLS_PER_PARENT, QString::number(per_parent_stats->calls_number));
if (per_frame_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_frame_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_FRAME, per_frame_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_FRAME, per_frame_stats->max_duration, "max ");
@ -339,7 +340,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
item->setText(COL_PERCENT_SUM_PER_THREAD, "");
}
const auto color = ::profiler_gui::EASY_GLOBALS.descriptors[block.tree->node->id()]->color();
const auto color = easyDescriptor(gui_block.tree.node->id()).color();
const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
const auto fgColor = 0x00ffffff - bgColor;
item->setBackgroundColor(bgColor);
@ -350,9 +351,9 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
size_t children_items_number = 0;
::profiler::timestamp_t children_duration = 0;
if (!block.tree->children.empty())
if (!gui_block.tree.children.empty())
{
children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, block.tree->children, item, item, thread_item, _left, _right, _strict, children_duration, _colorizeRows);
children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, gui_block.tree.children, item, item, thread_item, _left, _right, _strict, children_duration, _colorizeRows);
if (_safelocker.interrupted())
break;
}
@ -371,12 +372,12 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
//total_items += children_items_number + 1;
::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].tree_item = item_index;
gui_block.tree_item = item_index;
if (_colorizeRows)
item->colorize(_colorizeRows);
if (::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].expanded)
if (gui_block.expanded)
item->setExpanded(true);
}
@ -400,7 +401,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
//addTopLevelItem(item);
//m_roots[it.first] = item;
_items.push_back(item);
//_items.push_back(item);
_topLevelItems.emplace_back(it.first, item);
//++total_items;
@ -421,11 +422,13 @@ template <class T>
size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, EasyTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows)
{
size_t total_items = 0;
for (const auto& child : _children)
for (auto child_index : _children)
{
if (_safelocker.interrupted())
break;
auto& gui_block = easyBlock(child_index);
const auto& child = gui_block.tree;
const auto startTime = child.node->begin();
const auto endTime = child.node->end();
const auto duration = endTime - startTime;
@ -436,9 +439,9 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
continue;
}
auto item = new EasyTreeWidgetItem(&child, _parent);
auto item = new EasyTreeWidgetItem(child_index, _parent);
auto name = *child.node->name() != 0 ? child.node->name() : ::profiler_gui::EASY_GLOBALS.descriptors[child.node->id()]->name();
auto name = *child.node->name() != 0 ? child.node->name() : easyDescriptor(child.node->id()).name();
item->setText(COL_NAME, ::profiler_gui::toUnicode(name));
item->setTimeSmart(COL_DURATION, duration);
item->setTimeMs(COL_BEGIN, startTime - _beginTime);
@ -480,7 +483,7 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
}
if (per_thread_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_thread_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_THREAD, per_thread_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_THREAD, per_thread_stats->max_duration, "max ");
@ -499,7 +502,7 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
}
if (per_parent_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_parent_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_PARENT, per_parent_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_PARENT, per_parent_stats->max_duration, "max ");
@ -511,7 +514,7 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
item->setText(COL_NCALLS_PER_PARENT, QString::number(per_parent_stats->calls_number));
if (per_frame_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
if (per_frame_stats->calls_number > 1 || !EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_FRAME, per_frame_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_FRAME, per_frame_stats->max_duration, "max ");
@ -532,13 +535,13 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
item->setText(COL_PERCENT_SUM_PER_THREAD, "");
}
const auto color = ::profiler_gui::EASY_GLOBALS.descriptors[child.node->id()]->color();
const auto color = easyDescriptor(child.node->id()).color();
const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
const auto fgColor = 0x00ffffff - bgColor;
item->setBackgroundColor(bgColor);
item->setTextColor(fgColor);
auto item_index = static_cast<unsigned int>(_items.size());
auto item_index = static_cast<uint32_t>(_items.size());
_items.push_back(item);
size_t children_items_number = 0;
@ -564,12 +567,12 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
total_items += children_items_number + 1;
::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].tree_item = item_index;
gui_block.tree_item = item_index;
if (_colorizeRows)
item->colorize(_colorizeRows);
if (::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].expanded)
if (gui_block.expanded)
item->setExpanded(true);
}
else

View File

@ -112,7 +112,8 @@ int main(int argc, char* argv[])
::profiler::SerializedData serialized_blocks, serialized_descriptors;
::profiler::descriptors_list_t descriptors;
auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, threaded_trees, true);
::profiler::blocks_t blocks;
auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, blocks, threaded_trees, true);
auto end = std::chrono::system_clock::now();

View File

@ -198,7 +198,7 @@ typedef ::std::unordered_map<::std::string, ::profiler::block_id_t> IdMap;
automatically receive statistics update.
*/
::profiler::BlockStatistics* update_statistics(StatsMap& _stats_map, const ::profiler::BlocksTree& _current)
::profiler::BlockStatistics* update_statistics(StatsMap& _stats_map, const ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index)
{
auto duration = _current.node->duration();
//StatsMap::key_type key(_current.node->name());
@ -216,14 +216,14 @@ automatically receive statistics update.
if (duration > stats->max_duration)
{
// update max duration
stats->max_duration_block = _current.block_index;
stats->max_duration_block = _current_index;
stats->max_duration = duration;
}
if (duration < stats->min_duration)
{
// update min duraton
stats->min_duration_block = _current.block_index;
stats->min_duration_block = _current_index;
stats->min_duration = duration;
}
@ -234,7 +234,7 @@ automatically receive statistics update.
// This is first time the block appear in the file.
// Create new statistics.
auto stats = new ::profiler::BlockStatistics(duration, _current.block_index);
auto stats = new ::profiler::BlockStatistics(duration, _current_index);
//_stats_map.emplace(key, stats);
_stats_map.emplace(_current.node->id(), stats);
@ -243,289 +243,288 @@ automatically receive statistics update.
//////////////////////////////////////////////////////////////////////////
void update_statistics_recursive(StatsMap& _stats_map, ::profiler::BlocksTree& _current)
void update_statistics_recursive(StatsMap& _stats_map, ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::blocks_t& _blocks)
{
_current.per_frame_stats = update_statistics(_stats_map, _current);
for (auto& child : _current.children)
_current.per_frame_stats = update_statistics(_stats_map, _current, _current_index);
for (auto i : _current.children)
{
update_statistics_recursive(_stats_map, child);
update_statistics_recursive(_stats_map, _blocks[i], i, _blocks);
}
}
//////////////////////////////////////////////////////////////////////////
typedef ::std::map<::profiler::thread_id_t, StatsMap> PerThreadStats;
extern "C" ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics)
{
EASY_FUNCTION(::profiler::colors::Cyan);
extern "C" {
::std::ifstream inFile(filename, ::std::fstream::binary);
progress.store(0);
unsigned int fillTreesFromFile(::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics)
{
EASY_FUNCTION(::profiler::colors::Cyan);
if (!inFile.is_open())
return 0;
::std::ifstream inFile(filename, ::std::fstream::binary);
progress.store(0);
uint32_t total_blocks_number = 0;
inFile.read((char*)&total_blocks_number, sizeof(decltype(total_blocks_number)));
if (total_blocks_number == 0)
return 0;
if (!inFile.is_open())
uint64_t memory_size = 0;
inFile.read((char*)&memory_size, sizeof(decltype(memory_size)));
if (memory_size == 0)
return 0;
serialized_blocks.set(new char[memory_size]);
//memset(serialized_blocks[0], 0, memory_size);
uint32_t total_descriptors_number = 0;
inFile.read((char*)&total_descriptors_number, sizeof(decltype(total_descriptors_number)));
if (total_descriptors_number == 0)
return 0;
uint64_t descriptors_memory_size = 0;
inFile.read((char*)&descriptors_memory_size, sizeof(decltype(descriptors_memory_size)));
if (descriptors_memory_size == 0)
return 0;
descriptors.reserve(total_descriptors_number);
serialized_descriptors.set(new char[descriptors_memory_size]);
uint64_t i = 0;
while (!inFile.eof() && descriptors.size() < total_descriptors_number)
{
uint16_t sz = 0;
inFile.read((char*)&sz, sizeof(sz));
if (sz == 0)
return 0;
PerThreadStats thread_statistics, parent_statistics, frame_statistics;
unsigned int blocks_counter = 0;
//if (i + sz > descriptors_memory_size)
//{
// printf("FILE CORRUPTED\n");
// return 0;
//}
uint32_t total_blocks_number = 0;
inFile.read((char*)&total_blocks_number, sizeof(decltype(total_blocks_number)));
if (total_blocks_number == 0)
return 0;
char* data = serialized_descriptors[i];
inFile.read(data, sz);
auto descriptor = reinterpret_cast<::profiler::SerializedBlockDescriptor*>(data);
descriptors.push_back(descriptor);
uint64_t memory_size = 0;
inFile.read((char*)&memory_size, sizeof(decltype(memory_size)));
if (memory_size == 0)
return 0;
i += sz;
progress.store(static_cast<int>(10 * i / descriptors_memory_size));
}
serialized_blocks.set(new char[memory_size]);
//memset(serialized_blocks[0], 0, memory_size);
typedef ::std::map<::profiler::thread_id_t, StatsMap> PerThreadStats;
PerThreadStats thread_statistics, parent_statistics, frame_statistics;
IdMap identification_table;
i = 0;
uint32_t read_number = 0;
::profiler::block_index_t blocks_counter = 0;
_blocks.reserve(total_blocks_number);
while (!inFile.eof() && read_number < total_blocks_number)
{
EASY_BLOCK("Read thread data", ::profiler::colors::Darkgreen);
uint32_t total_descriptors_number = 0;
inFile.read((char*)&total_descriptors_number, sizeof(decltype(total_descriptors_number)));
if (total_descriptors_number == 0)
return 0;
::profiler::thread_id_t thread_id = 0;
inFile.read((char*)&thread_id, sizeof(decltype(thread_id)));
uint64_t descriptors_memory_size = 0;
inFile.read((char*)&descriptors_memory_size, sizeof(decltype(descriptors_memory_size)));
if (descriptors_memory_size == 0)
return 0;
uint32_t blocks_number_in_thread = 0;
inFile.read((char*)&blocks_number_in_thread, sizeof(decltype(blocks_number_in_thread)));
descriptors.reserve(total_descriptors_number);
serialized_descriptors.set(new char[descriptors_memory_size]);
uint64_t i = 0;
while (!inFile.eof() && descriptors.size() < total_descriptors_number)
auto& root = threaded_trees[thread_id];
const auto threshold = read_number + blocks_number_in_thread;
while (!inFile.eof() && read_number < threshold)
{
EASY_BLOCK("Read block", ::profiler::colors::Green);
++read_number;
uint16_t sz = 0;
inFile.read((char*)&sz, sizeof(sz));
if (sz == 0)
return 0;
//if (i + sz > descriptors_memory_size)
//{
// printf("FILE CORRUPTED\n");
// return 0;
//}
char* data = serialized_descriptors[i];
char* data = serialized_blocks[i];
inFile.read(data, sz);
auto descriptor = reinterpret_cast<::profiler::SerializedBlockDescriptor*>(data);
descriptors.push_back(descriptor);
i += sz;
progress.store(static_cast<int>(10 * i / descriptors_memory_size));
}
auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data);
IdMap identification_table;
_blocks.emplace_back();
::profiler::BlocksTree& tree = _blocks.back();
tree.node = baseData;// new ::profiler::SerializedBlock(sz, data);
const auto block_index = blocks_counter++;
i = 0;
uint32_t read_number = 0;
while (!inFile.eof() && read_number < total_blocks_number)
{
EASY_BLOCK("Read thread data", ::profiler::colors::Darkgreen);
auto& per_parent_statistics = parent_statistics[thread_id];
auto& per_thread_statistics = thread_statistics[thread_id];
auto descriptor = descriptors[baseData->id()];
::profiler::thread_id_t thread_id = 0;
inFile.read((char*)&thread_id, sizeof(decltype(thread_id)));
uint32_t blocks_number_in_thread = 0;
inFile.read((char*)&blocks_number_in_thread, sizeof(decltype(blocks_number_in_thread)));
auto& root = threaded_trees[thread_id];
const auto threshold = read_number + blocks_number_in_thread;
while (!inFile.eof() && read_number < threshold)
if (descriptor->type() == ::profiler::BLOCK_TYPE_THREAD_SIGN)
{
EASY_BLOCK("Read block", ::profiler::colors::Green);
root.thread_name = tree.node->name();
}
++read_number;
if (*tree.node->name() != 0)
{
// If block has runtime name then generate new id for such block.
// Blocks with the same name will have same id.
uint16_t sz = 0;
inFile.read((char*)&sz, sizeof(sz));
if (sz == 0)
return 0;
char* data = serialized_blocks[i];
inFile.read(data, sz);
i += sz;
auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data);
::profiler::BlocksTree tree;
tree.node = baseData;// new ::profiler::SerializedBlock(sz, data);
tree.block_index = blocks_counter++;
auto& per_parent_statistics = parent_statistics[thread_id];
auto& per_thread_statistics = thread_statistics[thread_id];
auto descriptor = descriptors[baseData->id()];
if (descriptor->type() == ::profiler::BLOCK_TYPE_THREAD_SIGN)
IdMap::key_type key(tree.node->name());
auto it = identification_table.find(key);
if (it != identification_table.end())
{
root.thread_name = tree.node->name();
// There is already block with such name, use it's id
baseData->setId(it->second);
}
if (*tree.node->name() != 0)
else
{
IdMap::key_type key(tree.node->name());
auto it = identification_table.find(key);
if (it != identification_table.end())
// There were no blocks with such name, generate new id and save it in the table for further usage.
auto id = static_cast<::profiler::block_id_t>(descriptors.size());
identification_table.emplace(key, id);
descriptors.push_back(descriptors[baseData->id()]);
baseData->setId(id);
}
}
if (!root.children.empty())
{
auto& back = _blocks[root.children.back()];
auto t1 = back.node->end();
auto mt0 = tree.node->begin();
if (mt0 < t1)//parent - starts earlier than last ends
{
//auto lower = ::std::lower_bound(root.children.begin(), root.children.end(), tree);
/**/
EASY_BLOCK("Find children", ::profiler::colors::Blue);
auto rlower1 = ++root.children.rbegin();
for (; rlower1 != root.children.rend() && !(mt0 > _blocks[*rlower1].node->begin()); ++rlower1);
auto lower = rlower1.base();
::std::move(lower, root.children.end(), ::std::back_inserter(tree.children));
root.children.erase(lower, root.children.end());
EASY_END_BLOCK;
::profiler::timestamp_t children_duration = 0;
if (gather_statistics)
{
baseData->setId(it->second);
EASY_BLOCK("Gather statistic within parent", ::profiler::colors::Magenta);
per_parent_statistics.clear();
//per_parent_statistics.reserve(tree.children.size()); // this gives slow-down on Windows
//per_parent_statistics.reserve(tree.children.size() * 2); // this gives no speed-up on Windows
// TODO: check this behavior on Linux
for (auto i : tree.children)
{
auto& child = _blocks[i];
child.per_parent_stats = update_statistics(per_parent_statistics, child, i);
children_duration += child.node->duration();
if (tree.depth < child.depth)
tree.depth = child.depth;
}
}
else
{
auto id = static_cast<::profiler::block_id_t>(descriptors.size());
identification_table.emplace(key, id);
descriptors.push_back(descriptors[baseData->id()]);
baseData->setId(id);
for (auto i : tree.children)
{
const auto& child = _blocks[i];
children_duration += child.node->duration();
if (tree.depth < child.depth)
tree.depth = child.depth;
}
}
++tree.depth;
}
if (!root.tree.children.empty())
{
auto& back = root.tree.children.back();
auto t1 = back.node->end();
auto mt0 = tree.node->begin();
if (mt0 < t1)//parent - starts earlier than last ends
{
//auto lower = ::std::lower_bound(root.children.begin(), root.children.end(), tree);
/**/
EASY_BLOCK("Find children", ::profiler::colors::Blue);
auto rlower1 = ++root.tree.children.rbegin();
for (; rlower1 != root.tree.children.rend(); ++rlower1)
{
if (mt0 > rlower1->node->begin())
{
break;
}
}
auto lower = rlower1.base();
::std::move(lower, root.tree.children.end(), ::std::back_inserter(tree.children));
root.tree.children.erase(lower, root.tree.children.end());
EASY_END_BLOCK;
::profiler::timestamp_t children_duration = 0;
if (gather_statistics)
{
EASY_BLOCK("Gather statistic within parent", ::profiler::colors::Magenta);
per_parent_statistics.clear();
//per_parent_statistics.reserve(tree.children.size()); // this gives slow-down on Windows
//per_parent_statistics.reserve(tree.children.size() * 2); // this gives no speed-up on Windows
// TODO: check this behavior on Linux
for (auto& child : tree.children)
{
child.per_parent_stats = update_statistics(per_parent_statistics, child);
children_duration += child.node->duration();
if (tree.depth < child.depth)
tree.depth = child.depth;
}
}
else
{
for (const auto& child : tree.children)
{
children_duration += child.node->duration();
if (tree.depth < child.depth)
tree.depth = child.depth;
}
}
++tree.depth;
}
}
root.tree.children.emplace_back(::std::move(tree));
if (gather_statistics)
{
EASY_BLOCK("Gather per thread statistics", ::profiler::colors::Coral);
auto& current = root.tree.children.back();
current.per_thread_stats = update_statistics(per_thread_statistics, current);
}
if (progress.load() < 0)
break;
progress.store(10 + static_cast<int>(80 * i / memory_size));
}
}
if (progress.load() < 0)
root.children.emplace_back(block_index);// ::std::move(tree));
if (gather_statistics)
{
EASY_BLOCK("Gather per thread statistics", ::profiler::colors::Coral);
tree.per_thread_stats = update_statistics(per_thread_statistics, tree, block_index);
}
if (progress.load() < 0)
break;
progress.store(10 + static_cast<int>(80 * i / memory_size));
}
}
if (progress.load() < 0)
{
serialized_blocks.clear();
threaded_trees.clear();
return 0;
}
EASY_BLOCK("Gather statistics for roots", ::profiler::colors::Purple);
if (gather_statistics)
{
::std::vector<::std::thread> statistics_threads;
statistics_threads.reserve(threaded_trees.size());
for (auto& it : threaded_trees)
{
serialized_blocks.clear();
threaded_trees.clear();
return 0;
auto& root = it.second;
root.thread_id = it.first;
//root.tree.shrink_to_fit();
auto& per_frame_statistics = frame_statistics[root.thread_id];
auto& per_parent_statistics = parent_statistics[it.first];
per_parent_statistics.clear();
statistics_threads.emplace_back(::std::thread([&per_parent_statistics, &per_frame_statistics, &_blocks](::profiler::BlocksTreeRoot& root)
{
for (auto i : root.children)
{
auto& frame = _blocks[i];
frame.per_parent_stats = update_statistics(per_parent_statistics, frame, i);
per_frame_statistics.clear();
update_statistics_recursive(per_frame_statistics, frame, i, _blocks);
if (root.depth < frame.depth)
root.depth = frame.depth;
}
++root.depth;
}, ::std::ref(root)));
}
EASY_BLOCK("Gather statistics for roots", ::profiler::colors::Purple);
if (gather_statistics)
{
::std::vector<::std::thread> statistics_threads;
statistics_threads.reserve(threaded_trees.size());
for (auto& it : threaded_trees)
{
auto& root = it.second;
root.thread_id = it.first;
root.tree.shrink_to_fit();
auto& per_frame_statistics = frame_statistics[root.thread_id];
auto& per_parent_statistics = parent_statistics[it.first];
per_parent_statistics.clear();
statistics_threads.emplace_back(::std::thread([&per_parent_statistics, &per_frame_statistics](::profiler::BlocksTreeRoot& root)
{
for (auto& frame : root.tree.children)
{
frame.per_parent_stats = update_statistics(per_parent_statistics, frame);
per_frame_statistics.clear();
update_statistics_recursive(per_frame_statistics, frame);
if (root.tree.depth < frame.depth)
root.tree.depth = frame.depth;
}
++root.tree.depth;
}, ::std::ref(root)));
}
int j = 0, n = static_cast<int>(statistics_threads.size());
for (auto& t : statistics_threads)
{
t.join();
progress.store(90 + (10 * ++j) / n);
}
}
else
int j = 0, n = static_cast<int>(statistics_threads.size());
for (auto& t : statistics_threads)
{
int j = 0, n = static_cast<int>(threaded_trees.size());
for (auto& it : threaded_trees)
{
auto& root = it.second;
root.thread_id = it.first;
root.tree.shrink_to_fit();
for (auto& frame : root.tree.children)
{
if (root.tree.depth < frame.depth)
root.tree.depth = frame.depth;
}
++root.tree.depth;
progress.store(90 + (10 * ++j) / n);
}
t.join();
progress.store(90 + (10 * ++j) / n);
}
// No need to delete BlockStatistics instances - they will be deleted inside BlocksTree destructors
}
else
{
int j = 0, n = static_cast<int>(threaded_trees.size());
for (auto& it : threaded_trees)
{
auto& root = it.second;
root.thread_id = it.first;
return blocks_counter;
}
//root.tree.shrink_to_fit();
for (auto i : root.children)
{
auto& frame = _blocks[i];
if (root.depth < frame.depth)
root.depth = frame.depth;
}
++root.depth;
progress.store(90 + (10 * ++j) / n);
}
}
// No need to delete BlockStatistics instances - they will be deleted inside BlocksTree destructors
return blocks_counter;
}