diff --git a/include/profiler/reader.h b/include/profiler/reader.h index 2ef4fc6..204c86a 100644 --- a/include/profiler/reader.h +++ b/include/profiler/reader.h @@ -178,6 +178,7 @@ namespace profiler { BlocksTree::children_t children; ///< List of children indexes BlocksTree::children_t sync; ///< List of context-switch events + BlocksTree::children_t events; ///< List of events indexes std::string thread_name; ///< Name of this thread ::profiler::timestamp_t active_time; ///< Active time of this thread (sum of all children duration) ::profiler::thread_id_t thread_id; ///< System Id of this thread @@ -190,6 +191,7 @@ namespace profiler { BlocksTreeRoot(This&& that) : children(::std::move(that.children)) , sync(::std::move(that.sync)) + , events(::std::move(that.events)) , thread_name(::std::move(that.thread_name)) , active_time(that.active_time) , thread_id(that.thread_id) @@ -201,6 +203,7 @@ namespace profiler { { children = ::std::move(that.children); sync = ::std::move(that.sync); + events = ::std::move(that.events); thread_name = ::std::move(that.thread_name); active_time = that.active_time; thread_id = that.thread_id; diff --git a/profiler_gui/easy_graphics_item.cpp b/profiler_gui/easy_graphics_item.cpp index fc26c0e..d8111fb 100644 --- a/profiler_gui/easy_graphics_item.cpp +++ b/profiler_gui/easy_graphics_item.cpp @@ -522,6 +522,72 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* } + + if (EASY_GLOBALS.enable_event_indicators && !m_pRoot->events.empty()) + { + auto first = ::std::lower_bound(m_pRoot->events.begin(), m_pRoot->events.end(), offset, [&sceneView](::profiler::block_index_t _index, qreal _value) + { + return sceneView->time2position(blocksTree(_index).node->begin()) < _value; + }); + + if (first != m_pRoot->events.end()) + { + if (first != m_pRoot->events.begin()) + --first; + } + else if (!m_pRoot->events.empty()) + { + first = m_pRoot->events.begin() + m_pRoot->events.size() - 1; + } + + previousColor = 0; + qreal prevRight = -1e100, top = y() + boundingRect().height() - 1, h = 3; + if (top + h < visibleBottom) + { + for (auto it = first, end = m_pRoot->events.end(); it != end; ++it) + { + const auto& item = blocksTree(*it); + auto left = sceneView->time2position(item.node->begin()); + + if (left > sceneRight) + break; // This is first totally invisible item. No need to check other items. + + decltype(left) width = 0.25; + if (left + width < sceneLeft) // This item is not visible + continue; + + left *= currentScale; + left -= dx; + width *= currentScale; + if (left + width <= prevRight) // This item is not visible + continue; + + if (left < prevRight) + { + width -= prevRight - left; + left = prevRight; + } + + if (width < 2) + width = 2; + + ::profiler::color_t color = easyDescriptor(item.node->id()).color(); + if (previousColor != color) + { + previousColor = color; + _painter->setBrush(QColor::fromRgb(color)); + _painter->setPen(QColor::fromRgb(BORDERS_COLOR & (0xffffffff - color))); + } + + rect.setRect(left, top, width, h); + _painter->drawRect(rect); + prevRight = left + width; + } + } + } + + + _painter->restore(); } diff --git a/profiler_gui/globals.cpp b/profiler_gui/globals.cpp index 027fe04..f4d24ee 100644 --- a/profiler_gui/globals.cpp +++ b/profiler_gui/globals.cpp @@ -47,6 +47,7 @@ namespace profiler_gui { : selected_thread(0U) , selected_block(::profiler_gui::numeric_max()) , chrono_text_position(ChronoTextPosition_Center) + , enable_event_indicators(true) , enable_statistics(true) , draw_graphics_items_borders(true) , display_only_relevant_stats(true) diff --git a/profiler_gui/globals.h b/profiler_gui/globals.h index 3e9c594..72bfa52 100644 --- a/profiler_gui/globals.h +++ b/profiler_gui/globals.h @@ -96,7 +96,8 @@ namespace profiler_gui { EasyBlocks gui_blocks; ///< Profiler graphics blocks builded by GUI ::profiler::thread_id_t selected_thread; ///< Current selected thread id ::profiler::block_index_t selected_block; ///< Current selected profiler block index - ChronometerTextPosition chrono_text_position; ///< + ChronometerTextPosition chrono_text_position; ///< Selected interval text position + 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 draw_graphics_items_borders; ///< Draw borders for graphics blocks or not 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 33dca9f..d35b34c 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -226,6 +226,11 @@ EasyMainWindow::EasyMainWindow() : Parent() action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status); connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange); + action = menu->addAction("Paint event indicators"); + action->setCheckable(true); + action->setChecked(EASY_GLOBALS.enable_event_indicators); + connect(action, &QAction::triggered, this, &This::onEventIndicatorsChange); + menu->addSeparator(); auto submenu = menu->addMenu("Chronometer text"); auto actionGroup = new QActionGroup(this); @@ -579,6 +584,12 @@ void EasyMainWindow::onChronoTextPosChanged(bool) emit EASY_GLOBALS.events.chronoPositionChanged(); } +void EasyMainWindow::onEventIndicatorsChange(bool _checked) +{ + EASY_GLOBALS.enable_event_indicators = _checked; + static_cast(m_graphicsView->widget())->view()->scene()->update(); +} + void EasyMainWindow::onEnableDisableStatistics(bool _checked) { EASY_GLOBALS.enable_statistics = _checked; @@ -700,47 +711,37 @@ void EasyMainWindow::loadSettings() auto last_file = settings.value("last_file"); if (!last_file.isNull()) - { m_lastFile = last_file.toString(); - } auto val = settings.value("chrono_text_position"); if (!val.isNull()) - { EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(val.toInt()); - } auto flag = settings.value("draw_graphics_items_borders"); if (!flag.isNull()) - { EASY_GLOBALS.draw_graphics_items_borders = flag.toBool(); - } flag = settings.value("collapse_items_on_tree_close"); if (!flag.isNull()) - { EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool(); - } flag = settings.value("all_items_expanded_by_default"); if (!flag.isNull()) - { EASY_GLOBALS.all_items_expanded_by_default = flag.toBool(); - } flag = settings.value("bind_scene_and_tree_expand_status"); if (!flag.isNull()) - { EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool(); - } + + flag = settings.value("enable_event_indicators"); + if (!flag.isNull()) + EASY_GLOBALS.enable_event_indicators = flag.toBool(); flag = settings.value("enable_statistics"); if (!flag.isNull()) - { EASY_GLOBALS.enable_statistics = flag.toBool(); - } QString encoding = settings.value("encoding", "UTF-8").toString(); auto default_codec_mib = QTextCodec::codecForName(encoding.toStdString().c_str())->mibEnum(); @@ -779,6 +780,7 @@ void EasyMainWindow::saveSettingsAndGeometry() 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("enable_event_indicators", EASY_GLOBALS.enable_event_indicators); settings.setValue("enable_statistics", EASY_GLOBALS.enable_statistics); settings.setValue("encoding", QTextCodec::codecForLocale()->name()); diff --git a/profiler_gui/main_window.h b/profiler_gui/main_window.h index 2c42029..47dee44 100644 --- a/profiler_gui/main_window.h +++ b/profiler_gui/main_window.h @@ -157,6 +157,7 @@ protected slots: void onExitClicked(bool); void onEncodingChanged(bool); void onChronoTextPosChanged(bool); + void onEventIndicatorsChange(bool); void onEnableDisableStatistics(bool); void onDrawBordersChanged(bool); void onCollapseItemsAfterCloseChanged(bool); diff --git a/src/reader.cpp b/src/reader.cpp index e5f290b..8e35321 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -402,7 +402,8 @@ extern "C" PROFILER_API::profiler::block_index_t fillTreesFromFile(::std::atomic inFile.read(data, sz); i += sz; auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); - if (descriptors[baseData->id()] == nullptr) + auto desc = descriptors[baseData->id()]; + if (desc == nullptr) return 0; auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); @@ -507,7 +508,8 @@ extern "C" PROFILER_API::profiler::block_index_t fillTreesFromFile(::std::atomic } root.children.emplace_back(block_index);// ::std::move(tree)); - + if (desc->type() == ::profiler::BLOCK_TYPE_EVENT) + root.events.emplace_back(block_index); if (gather_statistics)