diff --git a/profiler_gui/blocks_graphics_view.cpp b/profiler_gui/blocks_graphics_view.cpp index f2647c8..b2a10ab 100644 --- a/profiler_gui/blocks_graphics_view.cpp +++ b/profiler_gui/blocks_graphics_view.cpp @@ -541,7 +541,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index bool warned = false; qreal total_duration = 0, prev_end = 0, maxh = 0; qreal start_time = -1; - uint32_t i = 0; + uint32_t j = 0; for (auto child_index : _children) { auto& gui_block = easyBlock(child_index); @@ -567,7 +567,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index // duration = MIN_DURATION; //} - auto i = _item->addItem(level); + const auto i = _item->addItem(level); auto& b = _item->getItem(level, i); gui_block.graphics_item = _item->index(); @@ -610,12 +610,12 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index b.parent = _parent; b.setPos(xbegin, duration); //b.totalHeight = ::profiler_gui::GRAPHICS_ROW_SIZE + h; - b.state = i > 0 || level == 0 ? 0 : -1; + b.state = j > 0 || level == 0 ? 0 : -1; prev_end = xbegin + duration; total_duration = prev_end - start_time; - ++i; + ++j; } _height += ::profiler_gui::GRAPHICS_ROW_SIZE_FULL + maxh; diff --git a/profiler_gui/easy_graphics_item.cpp b/profiler_gui/easy_graphics_item.cpp index 23a2588..e3b6026 100644 --- a/profiler_gui/easy_graphics_item.cpp +++ b/profiler_gui/easy_graphics_item.cpp @@ -238,10 +238,9 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* if (top > visibleBottom) break; - int j = 1; - uint32_t par = ~0U; qreal prevRight = -1e100; - for (uint32_t i = m_levelsIndexes[l], end = static_cast(level.size()); i < end; ++i) + uint32_t neighbour = 0; + for (uint32_t i = m_levelsIndexes[l], end = static_cast(level.size()); i < end; ++i, ++neighbour) { //++iterations; @@ -252,6 +251,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* if (item.state != BLOCK_ITEM_UNCHANGED) { + neighbour = 0; // first block in parent's children list state = item.state; item.state = BLOCK_ITEM_DO_NOT_PAINT; } @@ -267,8 +267,14 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* { // This item is not visible //skip_children(next_level, item.children_begin); + if (item.parent != ~0U) - i += static_cast(easyBlock(item.parent).tree.children.size()) - 1; // Skip all neighbours + { + const auto n = static_cast(easyBlock(item.parent).tree.children.size()); + if (neighbour < n) + i += n - neighbour - 1; // Skip all neighbours + } + continue; } @@ -276,20 +282,15 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* { // Paint only first child which has own children - if (par != item.parent) - j = 1; - - par = item.parent; - if (item.children_begin == MAX_CHILD_INDEX && next_level < levelsNumber) - { - // This item has no children and would not be painted - ++j; - continue; - } + continue; // This item has no children and would not be painted if (item.parent != ~0U) - i += static_cast(easyBlock(item.parent).tree.children.size()) - j; // Skip all neighbours + { + const auto n = static_cast(easyBlock(item.parent).tree.children.size()); + if (neighbour < n) + i += n - neighbour - 1; // Skip all neighbours + } } const auto& itemBlock = easyBlock(item.block); @@ -687,7 +688,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* rect.setRect(left, top, width, h); _painter->drawRect(rect); - prevRight = left + width; + prevRight = left + width + 2; } } } diff --git a/profiler_gui/globals.cpp b/profiler_gui/globals.cpp index 8890ab1..4425f2d 100644 --- a/profiler_gui/globals.cpp +++ b/profiler_gui/globals.cpp @@ -69,6 +69,7 @@ namespace profiler_gui { , enable_event_indicators(true) , enable_statistics(true) , enable_zero_length(true) + , add_zero_blocks_to_hierarchy(false) , draw_graphics_items_borders(true) , hide_narrow_children(false) , display_only_relevant_stats(true) diff --git a/profiler_gui/globals.h b/profiler_gui/globals.h index 7e3473a..9e6ea82 100644 --- a/profiler_gui/globals.h +++ b/profiler_gui/globals.h @@ -119,6 +119,7 @@ namespace profiler_gui { bool enable_event_indicators; ///< Enable event indicators painting (These are narrow rectangles at the bottom of each thread) bool enable_statistics; ///< Enable gathering and using statistics (Disable if you want to consume less memory) bool enable_zero_length; ///< Enable zero length blocks (if true, then such blocks will have width == 1 pixel on each scale) + bool add_zero_blocks_to_hierarchy; ///< Enable adding zero blocks into hierarchy tree bool draw_graphics_items_borders; ///< Draw borders for graphics blocks or not bool hide_narrow_children; ///< Hide children for narrow graphics blocks bool display_only_relevant_stats; ///< Display only relevant information in ProfTreeWidget (excludes min, max, average times if there are only 1 calls number) diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index a40663a..15bd9f4 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -261,6 +261,15 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_lastAddress("127.0.0.1"), m_lastP action->setChecked(EASY_GLOBALS.only_current_thread_hierarchy); connect(action, &QAction::triggered, this, &This::onHierarchyFlagChange); + action = submenu->addAction("Add zero blocks to hierarchy"); + action->setCheckable(true); + action->setChecked(EASY_GLOBALS.add_zero_blocks_to_hierarchy); + connect(action, &QAction::triggered, [this](bool _checked) + { + EASY_GLOBALS.add_zero_blocks_to_hierarchy = _checked; + emit EASY_GLOBALS.events.hierarchyFlagChanged(_checked); + }); + action = submenu->addAction("Enable zero length blocks"); action->setCheckable(true); action->setChecked(EASY_GLOBALS.enable_zero_length); @@ -876,6 +885,10 @@ void EasyMainWindow::loadSettings() if (!flag.isNull()) EASY_GLOBALS.enable_zero_length = flag.toBool(); + flag = settings.value("add_zero_blocks_to_hierarchy"); + if (!flag.isNull()) + EASY_GLOBALS.add_zero_blocks_to_hierarchy = flag.toBool(); + flag = settings.value("bind_scene_and_tree_expand_status"); if (!flag.isNull()) EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool(); @@ -933,6 +946,7 @@ void EasyMainWindow::saveSettingsAndGeometry() settings.setValue("all_items_expanded_by_default", EASY_GLOBALS.all_items_expanded_by_default); settings.setValue("only_current_thread_hierarchy", EASY_GLOBALS.only_current_thread_hierarchy); settings.setValue("enable_zero_length", EASY_GLOBALS.enable_zero_length); + settings.setValue("add_zero_blocks_to_hierarchy", EASY_GLOBALS.add_zero_blocks_to_hierarchy); settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status); settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_indicators); settings.setValue("enable_statistics", EASY_GLOBALS.enable_statistics); diff --git a/profiler_gui/tree_widget_loader.cpp b/profiler_gui/tree_widget_loader.cpp index 442e79e..ca7f0be 100644 --- a/profiler_gui/tree_widget_loader.cpp +++ b/profiler_gui/tree_widget_loader.cpp @@ -151,19 +151,23 @@ void EasyTreeWidgetLoader::interrupt(bool _wait) void EasyTreeWidgetLoader::fillTree(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows) { interrupt(); - m_thread = ::std::move(::std::thread(&FillTreeClass::setTreeInternal1, ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), ::std::ref(_beginTime), _blocksNumber, ::std::ref(_blocksTree), _colorizeRows)); + m_thread = ::std::move(::std::thread(&FillTreeClass::setTreeInternal1, + ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), ::std::ref(_beginTime), + _blocksNumber, ::std::ref(_blocksTree), _colorizeRows, EASY_GLOBALS.add_zero_blocks_to_hierarchy)); } void EasyTreeWidgetLoader::fillTreeBlocks(const::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _beginTime, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows) { interrupt(); - m_thread = ::std::move(::std::thread(&FillTreeClass::setTreeInternal2, ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), _beginTime, ::std::ref(_blocks), _left, _right, _strict, _colorizeRows)); + m_thread = ::std::move(::std::thread(&FillTreeClass::setTreeInternal2, + ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), _beginTime, ::std::ref(_blocks), + _left, _right, _strict, _colorizeRows, EASY_GLOBALS.add_zero_blocks_to_hierarchy)); } ////////////////////////////////////////////////////////////////////////// template -void FillTreeClass::setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows) +void FillTreeClass::setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks) { _items.reserve(_blocksNumber + _blocksTree.size()); // _blocksNumber does not include Thread root blocks @@ -222,7 +226,7 @@ void FillTreeClass::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI item->setTimeSmart(COL_SELF_DURATION, root.active_time); ::profiler::timestamp_t children_duration = 0; - const auto children_items_number = FillTreeClass::setTreeInternal(_safelocker, _items, _beginTime, root.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, _addZeroBlocks); if (children_items_number > 0) { @@ -255,7 +259,7 @@ auto calculateTotalChildrenNumber(const ::profiler::BlocksTree& _tree) -> declty } template -void FillTreeClass::setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows) +void FillTreeClass::setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks) { //size_t blocksNumber = 0; //for (const auto& block : _blocks) @@ -402,7 +406,7 @@ void FillTreeClass::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI ::profiler::timestamp_t children_duration = 0; if (!gui_block.tree.children.empty()) { - children_items_number = FillTreeClass::setTreeInternal(_safelocker, _items, _beginTime, gui_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, _addZeroBlocks); if (_safelocker.interrupted()) break; } @@ -468,7 +472,7 @@ void FillTreeClass::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI } 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 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, bool _addZeroBlocks) { size_t total_items = 0; for (auto child_index : _children) @@ -481,12 +485,14 @@ size_t FillTreeClass::setTreeInternal(T& _safelocker, Items& _items, const :: const auto startTime = child.node->begin(); const auto endTime = child.node->end(); const auto duration = endTime - startTime; + + if (duration == 0 && !_addZeroBlocks) + continue; + _duration += duration; if (startTime > _right || endTime < _left) - { continue; - } auto item = new EasyTreeWidgetItem(child_index, _parent); @@ -613,7 +619,7 @@ size_t FillTreeClass::setTreeInternal(T& _safelocker, Items& _items, const :: ::profiler::timestamp_t children_duration = 0; if (!child.children.empty()) { - children_items_number = FillTreeClass::setTreeInternal(_safelocker, _items, _beginTime, child.children, item, _frame ? _frame : item, _thread, _left, _right, _strict, children_duration, _colorizeRows); + children_items_number = FillTreeClass::setTreeInternal(_safelocker, _items, _beginTime, child.children, item, _frame ? _frame : item, _thread, _left, _right, _strict, children_duration, _colorizeRows, _addZeroBlocks); if (_safelocker.interrupted()) break; } diff --git a/profiler_gui/tree_widget_loader.h b/profiler_gui/tree_widget_loader.h index 62f3bcc..1297533 100644 --- a/profiler_gui/tree_widget_loader.h +++ b/profiler_gui/tree_widget_loader.h @@ -98,9 +98,9 @@ public: template struct FillTreeClass Q_DECL_FINAL { - static void setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows); - static void setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows); - static size_t setTreeInternal(T& _safelocker, Items& _items, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, EasyTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows); + static void setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks); + static void setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks); + static size_t setTreeInternal(T& _safelocker, Items& _items, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, EasyTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows, bool _addZeroBlocks); }; //////////////////////////////////////////////////////////////////////////