From 9560c5b5cff8a4145bee6c20cd01ad9c96f9eb95 Mon Sep 17 00:00:00 2001 From: Victor Zarubkin Date: Tue, 30 Aug 2016 22:51:18 +0300 Subject: [PATCH] (profiler_gui) Memory consumption optimization + File reading speed-up. --- include/profiler/reader.h | 50 ++- profiler_gui/blocks_graphics_view.cpp | 118 +++---- profiler_gui/blocks_graphics_view.h | 8 +- profiler_gui/blocks_tree_widget.cpp | 94 ++--- profiler_gui/common_types.h | 62 +++- profiler_gui/globals.h | 32 +- profiler_gui/graphics_scrollbar.cpp | 14 +- profiler_gui/graphics_scrollbar.h | 8 +- profiler_gui/main_window.cpp | 97 +++--- profiler_gui/main_window.h | 4 +- profiler_gui/tree_widget_item.cpp | 24 +- profiler_gui/tree_widget_item.h | 8 +- profiler_gui/tree_widget_loader.cpp | 103 +++--- reader/main.cpp | 3 +- src/reader.cpp | 475 +++++++++++++------------- 15 files changed, 581 insertions(+), 519 deletions(-) diff --git a/include/profiler/reader.h b/include/profiler/reader.h index b851350..c46acbd 100644 --- a/include/profiler/reader.h +++ b/include/profiler/reader.h @@ -72,23 +72,21 @@ namespace profiler { public: - typedef ::std::vector children_t; + typedef ::std::vector 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& 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& 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 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); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/blocks_graphics_view.cpp b/profiler_gui/blocks_graphics_view.cpp index dfa3dea..14f8808 100644 --- a/profiler_gui/blocks_graphics_view.cpp +++ b/profiler_gui/blocks_graphics_view.cpp @@ -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(); - 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(); + 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(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; diff --git a/profiler_gui/blocks_graphics_view.h b/profiler_gui/blocks_graphics_view.h index e51522d..e0ceb31 100644 --- a/profiler_gui/blocks_graphics_view.h +++ b/profiler_gui/blocks_graphics_view.h @@ -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 DrawIndexes; typedef ::std::vector 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: diff --git a/profiler_gui/blocks_tree_widget.cpp b/profiler_gui/blocks_tree_widget.cpp index 877c723..a64931b 100644 --- a/profiler_gui/blocks_tree_widget.cpp +++ b/profiler_gui/blocks_tree_widget.cpp @@ -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(); 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(_item)->block()->block_index].expanded = true; + static_cast(_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(_item)->block()->block_index].expanded = false; + static_cast(_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(_item)->block()->block_index; + EASY_GLOBALS.selected_block = static_cast(_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 { diff --git a/profiler_gui/common_types.h b/profiler_gui/common_types.h index 1b48127..fa07d8b 100644 --- a/profiler_gui/common_types.h +++ b/profiler_gui/common_types.h @@ -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 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 EasyItems; +typedef ::std::vector 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 TreeBlocks; +typedef ::std::vector TreeBlocks; ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/globals.h b/profiler_gui/globals.h index ca2a1d4..0a0eee8 100644 --- a/profiler_gui/globals.h +++ b/profiler_gui/globals.h @@ -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 EasyBlocks; - template 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 + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/graphics_scrollbar.cpp b/profiler_gui/graphics_scrollbar.cpp index 88d5fec..2260857 100644 --- a/profiler_gui/graphics_scrollbar.cpp +++ b/profiler_gui/graphics_scrollbar.cpp @@ -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); } } diff --git a/profiler_gui/graphics_scrollbar.h b/profiler_gui/graphics_scrollbar.h index b70a1af..85e19a9 100644 --- a/profiler_gui/graphics_scrollbar.h +++ b/profiler_gui/graphics_scrollbar.h @@ -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); } diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index 8edf2da..945ab3f 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -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(::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(::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(::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(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(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(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(::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(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(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(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); } diff --git a/profiler_gui/main_window.h b/profiler_gui/main_window.h index 138ca85..91160d4 100644 --- a/profiler_gui/main_window.h +++ b/profiler_gui/main_window.h @@ -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. diff --git a/profiler_gui/tree_widget_item.cpp b/profiler_gui/tree_widget_item.cpp index 003fc1d..1a2c0a6 100644 --- a/profiler_gui/tree_widget_item.cpp +++ b/profiler_gui/tree_widget_item.cpp @@ -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; } ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/tree_widget_item.h b/profiler_gui/tree_widget_item.h index 466b9f6..1b12d21 100644 --- a/profiler_gui/tree_widget_item.h +++ b/profiler_gui/tree_widget_item.h @@ -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(), 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; diff --git a/profiler_gui/tree_widget_loader.cpp b/profiler_gui/tree_widget_loader.cpp index 8248e81..2931382 100644 --- a/profiler_gui/tree_widget_loader.cpp +++ b/profiler_gui/tree_widget_loader.cpp @@ -126,7 +126,7 @@ void FillTreeClass::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::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::setTreeInternal(_safelocker, _items, _beginTime, block.children, item, nullptr, item, _beginTime, finishtime + 1000000000ULL, false, children_duration, _colorizeRows); + const auto children_items_number = FillTreeClass::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::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::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::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::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::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::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::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::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::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::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::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::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::setTreeInternal(_safelocker, _items, _beginTime, block.tree->children, item, item, thread_item, _left, _right, _strict, children_duration, _colorizeRows); + children_items_number = FillTreeClass::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::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::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 size_t FillTreeClass::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::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::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::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::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::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(_items.size()); + auto item_index = static_cast(_items.size()); _items.push_back(item); size_t children_items_number = 0; @@ -564,12 +567,12 @@ size_t FillTreeClass::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 diff --git a/reader/main.cpp b/reader/main.cpp index ed696d1..6170bcb 100644 --- a/reader/main.cpp +++ b/reader/main.cpp @@ -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(); diff --git a/src/reader.cpp b/src/reader.cpp index aee8d86..d3ba142 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -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& 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& 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(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(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(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(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(statistics_threads.size()); - for (auto& t : statistics_threads) - { - t.join(); - progress.store(90 + (10 * ++j) / n); - } - } - else + int j = 0, n = static_cast(statistics_threads.size()); + for (auto& t : statistics_threads) { - int j = 0, n = static_cast(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(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; }