From b73044fddd30b4fda3e7a0f7a26dc00cf5cb5a0a Mon Sep 17 00:00:00 2001 From: Victor Zarubkin Date: Thu, 14 Dec 2017 23:12:27 +0300 Subject: [PATCH] #31 [Core] Fixed issue with storing arbitrary value while dumping. // [GUI] Further values viewer progress. --- easy_profiler_core/profile_manager.cpp | 15 +- easy_profiler_core/reader.cpp | 10 +- profiler_gui/arbitrary_value_inspector.cpp | 167 ++++++++++++--------- profiler_gui/common_functions.h | 56 ++++--- profiler_gui/descriptors_tree_widget.cpp | 23 ++- profiler_gui/descriptors_tree_widget.h | 3 +- sample/main.cpp | 30 +++- 7 files changed, 192 insertions(+), 112 deletions(-) diff --git a/easy_profiler_core/profile_manager.cpp b/easy_profiler_core/profile_manager.cpp index 9e66606..eb36baf 100644 --- a/easy_profiler_core/profile_manager.cpp +++ b/easy_profiler_core/profile_manager.cpp @@ -788,18 +788,11 @@ const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _d void ProfileManager::storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, size_t _size, bool _isArray, ValueId _vin) { const auto state = m_profilerStatus.load(std::memory_order_acquire); - if (state == EASY_PROF_DISABLED || (_desc->m_status & profiler::ON) == 0) + if (state != EASY_PROF_ENABLED || (_desc->m_status & profiler::ON) == 0) return; - if (state == EASY_PROF_DUMP) - { - if (THIS_THREAD == nullptr || THIS_THREAD->blocks.openedList.empty()) - return; - } - else if (THIS_THREAD == nullptr) - { + if (THIS_THREAD == nullptr) registerThread(); - } #if EASY_ENABLE_BLOCK_STATUS != 0 if (!THIS_THREAD->allowChildren && (_desc->m_status & FORCE_ON_FLAG) == 0) @@ -819,7 +812,7 @@ bool ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, cons if (state == EASY_PROF_DUMP) { - if (THIS_THREAD == nullptr || THIS_THREAD->blocks.openedList.empty()) + if (THIS_THREAD == nullptr || THIS_THREAD->halt) return false; } else if (THIS_THREAD == nullptr) @@ -846,7 +839,7 @@ bool ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, cons if (state == EASY_PROF_DUMP) { - if (THIS_THREAD == nullptr || THIS_THREAD->blocks.openedList.empty()) + if (THIS_THREAD == nullptr || THIS_THREAD->halt) return false; } else if (THIS_THREAD == nullptr) diff --git a/easy_profiler_core/reader.cpp b/easy_profiler_core/reader.cpp index d2ac4c6..967666a 100644 --- a/easy_profiler_core/reader.cpp +++ b/easy_profiler_core/reader.cpp @@ -546,7 +546,7 @@ extern "C" { descriptors.push_back(descriptor); i += sz; - auto oldprogress = progress.exchange(static_cast(15 * i / descriptors_memory_size), ::std::memory_order_release); + oldprogress = progress.exchange(static_cast(15 * i / descriptors_memory_size), ::std::memory_order_release); if (oldprogress < 0) { _log << "Reading was interrupted"; @@ -642,7 +642,7 @@ extern "C" { } } - auto oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); + oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); if (oldprogress < 0) { _log << "Reading was interrupted"; @@ -808,7 +808,7 @@ extern "C" { } } - auto oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); + oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); if (oldprogress < 0) { _log << "Reading was interrupted"; @@ -817,7 +817,8 @@ extern "C" { } } - if (progress.load(::std::memory_order_acquire) < 0) + oldprogress = progress.exchange(90, ::std::memory_order_release); + if (oldprogress < 0) { _log << "Reading was interrupted"; return 0; // Loading interrupted @@ -926,6 +927,7 @@ extern "C" { } // No need to delete BlockStatistics instances - they will be deleted inside BlocksTree destructors + progress.store(100, ::std::memory_order_release); return blocks_counter; } diff --git a/profiler_gui/arbitrary_value_inspector.cpp b/profiler_gui/arbitrary_value_inspector.cpp index 0581437..8647fd4 100644 --- a/profiler_gui/arbitrary_value_inspector.cpp +++ b/profiler_gui/arbitrary_value_inspector.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include "arbitrary_value_inspector.h" #include "treeview_first_column_delegate.h" @@ -354,17 +355,18 @@ EasyArbitraryValuesTreeItem::~EasyArbitraryValuesTreeItem() enum class ArbitraryColumns : uint8_t { - Name = 0, - Type, + Type = 0, + Name, Value, Vin, Count }; -inline EASY_CONSTEXPR_FCN int int_cast(ArbitraryColumns col) { - return static_cast(col); -} +struct UsedValueTypes { + QTreeWidgetItem* items[int_cast(profiler::DataType::TypesCount)]; + UsedValueTypes(int = 0) { memset(items, 0, sizeof(items)); } +}; EasyArbitraryValuesWidget::EasyArbitraryValuesWidget(QWidget* _parent) : Parent(_parent) @@ -384,8 +386,8 @@ EasyArbitraryValuesWidget::EasyArbitraryValuesWidget(QWidget* _parent) // m_treeWidget->header()->setFont(f); auto headerItem = new QTreeWidgetItem(); - headerItem->setText(int_cast(ArbitraryColumns::Name), "Name"); headerItem->setText(int_cast(ArbitraryColumns::Type), "Type"); + headerItem->setText(int_cast(ArbitraryColumns::Name), "Name"); headerItem->setText(int_cast(ArbitraryColumns::Value), "Value"); headerItem->setText(int_cast(ArbitraryColumns::Vin), "ID"); m_treeWidget->setHeaderItem(headerItem); @@ -444,6 +446,7 @@ void EasyArbitraryValuesWidget::rebuild() void EasyArbitraryValuesWidget::buildTree(profiler::thread_id_t _threadId, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId) { m_treeWidget->clear(); + m_treeWidget->setColumnHidden(int_cast(ArbitraryColumns::Value), profiler_gui::is_max(_blockIndex)); if (_threadId != 0) { @@ -466,56 +469,44 @@ void EasyArbitraryValuesWidget::buildTree(profiler::thread_id_t _threadId, profi QTreeWidgetItem* EasyArbitraryValuesWidget::buildTreeForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId) { - //std::unordered_set > vins; - //std::unordered_set names; - auto rootItem = new QTreeWidgetItem(QTreeWidgetItem::UserType); - rootItem->setText(0, profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, _threadRoot, EASY_GLOBALS.hex_thread_id)); + rootItem->setText(int_cast(ArbitraryColumns::Type), QStringLiteral("Thread")); + rootItem->setText(int_cast(ArbitraryColumns::Name), + profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, _threadRoot, EASY_GLOBALS.hex_thread_id)); - if (_blockIndex != ::profiler_gui::numeric_max()) + const bool hasConcreteBlock = !profiler_gui::is_max(_blockIndex); + if (hasConcreteBlock) { const auto& block = easyBlocksTree(_blockIndex); - - auto blockItem = new QTreeWidgetItem(rootItem, QTreeWidgetItem::UserType); - blockItem->setText(int_cast(ArbitraryColumns::Name), easyBlockName(block)); - - for (auto childIndex : block.children) + const auto& desc = easyDescriptor(block.node->id()); + if (desc.type() == profiler::BlockType::Value) { - const auto& child = easyBlocksTree(childIndex); - const auto& desc = easyDescriptor(child.node->id()); - if (desc.type() == profiler::BlockType::Value) - { - auto vin = child.value->value_id(); - -// if (vin == 0) -// { -// auto result = names.insert(desc.name()).second; -// if (!result) -// continue; // already in set -// } -// else -// { -// auto result = vins.insert(vin).second; -// if (!result) -// continue; // already in set -// } - - auto valueItem = new QTreeWidgetItem(blockItem, QTreeWidgetItem::UserType); - valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); - valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*child.value)); - valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(vin, 0, 16)); - valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*child.value)); - } + auto valueItem = new QTreeWidgetItem(rootItem, QTreeWidgetItem::UserType + 1); + valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*block.value)); + valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); + valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(block.value->value_id(), 0, 16)); + valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*block.value)); + return rootItem; } - return rootItem; + _blockId = block.node->id(); } - if (_blockId == profiler_gui::numeric_max()) - return rootItem; + const bool noId = profiler_gui::is_max(_blockId); + QTreeWidgetItem* blockItem = nullptr; + if (!noId) + { + blockItem = new QTreeWidgetItem(rootItem, QTreeWidgetItem::UserType); + blockItem->setText(int_cast(ArbitraryColumns::Type), QStringLiteral("Block")); + if (hasConcreteBlock) + blockItem->setText(int_cast(ArbitraryColumns::Name), easyBlockName(_blockIndex)); + else + blockItem->setText(int_cast(ArbitraryColumns::Name), easyDescriptor(_blockId).name()); + } - auto blockItem = new QTreeWidgetItem(rootItem, QTreeWidgetItem::UserType); - blockItem->setText(int_cast(ArbitraryColumns::Name), easyDescriptor(_blockId).name()); + std::unordered_map > blocks; + std::unordered_map > vins; + std::unordered_map names; std::vector stack; for (auto childIndex : _threadRoot.children) @@ -527,36 +518,76 @@ QTreeWidgetItem* EasyArbitraryValuesWidget::buildTreeForThread(const profiler::B stack.pop_back(); const auto& block = easyBlocksTree(i); - if (block.node->id() == _blockId || easyDescriptor(block.node->id()).id() == _blockId) + if (noId || block.node->id() == _blockId || easyDescriptor(block.node->id()).id() == _blockId) { for (auto c : block.children) { + if (noId) + stack.push_back(c); + const auto& child = easyBlocksTree(c); const auto& desc = easyDescriptor(child.node->id()); - if (desc.type() == profiler::BlockType::Value) + if (desc.type() != profiler::BlockType::Value) + continue; + + if (blockItem == nullptr) { - auto vin = child.value->value_id(); - -// if (vin == 0) -// { -// auto result = names.insert(desc.name()).second; -// if (!result) -// continue; // already in set -// } -// else -// { -// auto result = vins.insert(vin).second; -// if (!result) -// continue; // already in set -// } - - auto valueItem = new QTreeWidgetItem(blockItem, QTreeWidgetItem::UserType); - valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); - valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*child.value)); - valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(vin, 0, 16)); - valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*child.value)); + const auto id = block.node->id(); + auto it = blocks.find(id); + if (it != blocks.end()) + { + blockItem = it->second; + } + else + { + blockItem = new QTreeWidgetItem(rootItem, QTreeWidgetItem::UserType); + blockItem->setText(int_cast(ArbitraryColumns::Type), QStringLiteral("Block")); + blockItem->setText(int_cast(ArbitraryColumns::Name), easyBlockName(block)); + blocks.emplace(id, blockItem); + } } + + const auto typeIndex = int_cast(child.value->type()); + auto vin = child.value->value_id(); + + QTreeWidgetItem** usedItems = nullptr; + QTreeWidgetItem* valueItem = nullptr; + if (vin == 0) + { + auto result = names.emplace(desc.name(), 0); + usedItems = result.first->second.items; + if (!result.second && (valueItem = *(usedItems + typeIndex))) + { + if (i == _blockIndex) + valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*child.value)); + continue; // already in set + } + } + else + { + auto result = vins.emplace(vin, 0); + usedItems = result.first->second.items; + if (!result.second && (valueItem = *(usedItems + typeIndex))) + { + if (i == _blockIndex) + valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*child.value)); + continue; // already in set + } + } + + valueItem = new QTreeWidgetItem(blockItem, QTreeWidgetItem::UserType + 1); + valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*child.value)); + valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); + valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(vin, 0, 16)); + + if (i == _blockIndex) + valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*child.value)); + + *(usedItems + typeIndex) = valueItem; } + + if (noId) + blockItem = nullptr; } else { diff --git a/profiler_gui/common_functions.h b/profiler_gui/common_functions.h index 5a52922..0e5539c 100644 --- a/profiler_gui/common_functions.h +++ b/profiler_gui/common_functions.h @@ -58,6 +58,7 @@ #include #include #include +#include #include "common_types.h" ////////////////////////////////////////////////////////////////////////// @@ -90,55 +91,68 @@ EASY_FORCE_INLINE qreal microseconds2units(qreal _value) { //return _value * 1e-3; } +#ifdef EASY_CONSTEXPR_AVAILABLE +template +EASY_FORCE_INLINE EASY_CONSTEXPR_FCN typename ::std::underlying_type::type int_cast(TEnum _enumValue) { + return static_cast::type>(_enumValue); +} +#else +# define int_cast(_enumValue) static_cast::type>(_enumValue) +#endif + ////////////////////////////////////////////////////////////////////////// namespace profiler_gui { ////////////////////////////////////////////////////////////////////////// -template inline T numeric_max() { +template inline +EASY_CONSTEXPR_FCN T numeric_max() { return ::std::numeric_limits::max(); } -template inline T numeric_max(T) { +template inline +EASY_CONSTEXPR_FCN T numeric_max(T) { return ::std::numeric_limits::max(); } -template inline void set_max(T& _value) { - _value = ::std::numeric_limits::max(); -} - -template inline bool is_max(const T& _value) { +template inline +EASY_CONSTEXPR_FCN bool is_max(const T& _value) { return _value == ::std::numeric_limits::max(); } +template inline +void set_max(T& _value) { + _value = ::std::numeric_limits::max(); +} + ////////////////////////////////////////////////////////////////////////// -inline QRgb toRgb(uint32_t _red, uint32_t _green, uint32_t _blue) { +inline EASY_CONSTEXPR_FCN QRgb toRgb(uint32_t _red, uint32_t _green, uint32_t _blue) { return (_red << 16) + (_green << 8) + _blue; } -inline QRgb fromProfilerRgb(uint32_t _red, uint32_t _green, uint32_t _blue) { - if (_red == 0 && _green == 0 && _blue == 0) - return ::profiler::colors::Default; - return toRgb(_red, _green, _blue) | 0x00141414; +inline EASY_CONSTEXPR_FCN QRgb fromProfilerRgb(uint32_t _red, uint32_t _green, uint32_t _blue) { + return _red == 0 && _green == 0 && _blue == 0 ? ::profiler::colors::Default : toRgb(_red, _green, _blue) | 0x00141414; } -inline bool isLightColor(::profiler::color_t _color) { - const auto sum = 255. - (((_color & 0x00ff0000) >> 16) * 0.299 + ((_color & 0x0000ff00) >> 8) * 0.587 + (_color & 0x000000ff) * 0.114); - return sum < 76.5 || ((_color & 0xff000000) >> 24) < 0x80; +EASY_FORCE_INLINE EASY_CONSTEXPR_FCN qreal colorSum(::profiler::color_t _color) { + return 255. - (((_color & 0x00ff0000) >> 16) * 0.299 + ((_color & 0x0000ff00) >> 8) * 0.587 + (_color & 0x000000ff) * 0.114); } -inline bool isLightColor(::profiler::color_t _color, qreal _maxSum) { - const auto sum = 255. - (((_color & 0x00ff0000) >> 16) * 0.299 + ((_color & 0x0000ff00) >> 8) * 0.587 + (_color & 0x000000ff) * 0.114); - return sum < _maxSum || ((_color & 0xff000000) >> 24) < 0x80; +inline EASY_CONSTEXPR_FCN bool isLightColor(::profiler::color_t _color) { + return colorSum(_color) < 76.5 || ((_color & 0xff000000) >> 24) < 0x80; } -inline ::profiler::color_t textColorForFlag(bool _is_light) { +inline EASY_CONSTEXPR_FCN bool isLightColor(::profiler::color_t _color, qreal _maxSum) { + return colorSum(_color) < _maxSum || ((_color & 0xff000000) >> 24) < 0x80; +} + +inline EASY_CONSTEXPR_FCN ::profiler::color_t textColorForFlag(bool _is_light) { return _is_light ? ::profiler::colors::Dark : ::profiler::colors::CreamWhite; } -inline ::profiler::color_t textColorForRgb(::profiler::color_t _color) { +inline EASY_CONSTEXPR_FCN ::profiler::color_t textColorForRgb(::profiler::color_t _color) { return isLightColor(_color) ? ::profiler::colors::Dark : ::profiler::colors::CreamWhite; } @@ -159,7 +173,7 @@ QString timeStringIntNs(TimeUnits _units, ::profiler::timestamp_t _interval); ////////////////////////////////////////////////////////////////////////// inline double percentReal(::profiler::timestamp_t _partial, ::profiler::timestamp_t _total) { - return _total ? 100. * static_cast(_partial) / static_cast(_total) : 0.; + return _total != 0 ? 100. * static_cast(_partial) / static_cast(_total) : 0.; } inline int percent(::profiler::timestamp_t _partial, ::profiler::timestamp_t _total) { diff --git a/profiler_gui/descriptors_tree_widget.cpp b/profiler_gui/descriptors_tree_widget.cpp index ccad69f..9ac42aa 100644 --- a/profiler_gui/descriptors_tree_widget.cpp +++ b/profiler_gui/descriptors_tree_widget.cpp @@ -226,6 +226,7 @@ QVariant EasyDescWidgetItem::data(int _column, int _role) const case Type::File: return QStringLiteral("File"); case Type::Event: return QStringLiteral("Event"); case Type::Block: return QStringLiteral("Block"); + case Type::Value: return QStringLiteral("Arbitrary Value"); } } else if (_role == Qt::DisplayRole) @@ -235,6 +236,7 @@ QVariant EasyDescWidgetItem::data(int _column, int _role) const case Type::File: return QStringLiteral("F"); case Type::Event: return QStringLiteral("E"); case Type::Block: return QStringLiteral("B"); + case Type::Value: return QStringLiteral("V"); } } } @@ -432,10 +434,20 @@ void EasyDescTreeWidget::build() item->setData(DESC_COL_FILE_LINE, Qt::UserRole, desc->line()); item->setText(DESC_COL_NAME, desc->name()); - if (desc->type() == ::profiler::BlockType::Block) - item->setType(EasyDescWidgetItem::Type::Block); - else - item->setType(EasyDescWidgetItem::Type::Event); + switch (desc->type()) + { + case ::profiler::BlockType::Block: + item->setType(EasyDescWidgetItem::Type::Block); + break; + + case ::profiler::BlockType::Event: + item->setType(EasyDescWidgetItem::Type::Event); + break; + + case ::profiler::BlockType::Value: + item->setType(EasyDescWidgetItem::Type::Value); + break; + } item->setFont(DESC_COL_STATUS, f); item->setText(DESC_COL_STATUS, statusText(desc->status())); @@ -583,7 +595,10 @@ void EasyDescTreeWidget::resizeColumnsToContents() void EasyDescTreeWidget::onSelectedBlockChange(uint32_t _block_index) { if (::profiler_gui::is_max(_block_index)) + { + setCurrentItem(nullptr); return; + } auto item = m_items[easyBlocksTree(_block_index).node->id()]; if (item == nullptr) diff --git a/profiler_gui/descriptors_tree_widget.h b/profiler_gui/descriptors_tree_widget.h index af81f75..3a00d67 100644 --- a/profiler_gui/descriptors_tree_widget.h +++ b/profiler_gui/descriptors_tree_widget.h @@ -78,7 +78,8 @@ public: { File, Event, - Block + Block, + Value }; private: diff --git a/sample/main.cpp b/sample/main.cpp index f62573c..b098135 100644 --- a/sample/main.cpp +++ b/sample/main.cpp @@ -8,6 +8,7 @@ #include #include +#include #include std::condition_variable cv; @@ -19,7 +20,7 @@ int MODELLING_STEPS = 1500; int RENDER_STEPS = 1500; int RESOURCE_LOADING_COUNT = 50; -//#define SAMPLE_NETWORK_TEST +#define SAMPLE_NETWORK_TEST void localSleep(int magic=200000) { @@ -36,11 +37,17 @@ void loadingResources(){ void prepareMath(){ EASY_FUNCTION(profiler::colors::Green); + uint64_t sum = 0; int* intarray = new int[OBJECTS]; for (int i = 0; i < OBJECTS; ++i) + { intarray[i] = i * i; + sum += i * i; + } delete[] intarray; //std::this_thread::sleep_for(std::chrono::milliseconds(3)); + + EASY_VALUE("sum", sum, profiler::colors::Blue); } void calcIntersect(){ @@ -75,7 +82,9 @@ void calcPhys(){ double calcSubbrain(int i) { EASY_FUNCTION(profiler::colors::Navy); - return i * i * i - i / 10 + (OBJECTS - i) * 7 ; + auto val = i * i * i - i / 10 + (OBJECTS - i) * 7 ; + EASY_VALUE("subbrainResult", val, profiler::colors::DarkRed); + return val; } void calcBrain(){ @@ -154,15 +163,23 @@ void modellingThread(){ //cv.wait(lk, []{return g_i == 1; }); EASY_THREAD("Modelling"); #ifdef SAMPLE_NETWORK_TEST + uint64_t step = 0; while (true) { #else for (int i = 0; i < MODELLING_STEPS; i++){ #endif EASY_END_BLOCK; - EASY_NONSCOPED_BLOCK("Frame"); + EASY_NONSCOPED_BLOCK("Frame", true, 15., profiler::ON, -5.f, profiler::colors::Red); modellingStep(); localSleep(1200000); + + ++step; + EASY_VALUE("step", step, profiler::colors::Gold); + if (step > 10000000) + step = 0; + + EASY_TEXT("Test String", "Some short text. Hey!", profiler::colors::Red); //std::this_thread::sleep_for(std::chrono::milliseconds(20)); } EASY_END_BLOCK; @@ -214,6 +231,13 @@ int main(int argc, char* argv[]) EASY_MAIN_THREAD; profiler::startListen(); + constexpr int grrr[] {2, -3, 4}; + auto pppp = &grrr; + EASY_ARRAY("threads count", grrr, 3, false, true, "blabla", profiler::colors::Blue/*, EASY_VIN("threads count")*/, profiler::OFF); + + int* intPtr = new int(2); + EASY_VALUE("count", *intPtr); + std::vector threads; //for (int i=0; i < 3; i++) {