diff --git a/easy_profiler_core/block.cpp b/easy_profiler_core/block.cpp index f0fae54..c399913 100644 --- a/easy_profiler_core/block.cpp +++ b/easy_profiler_core/block.cpp @@ -54,17 +54,25 @@ using namespace profiler; #ifndef EASY_PROFILER_API_DISABLED +Event::Event(timestamp_t _begin_time) : m_begin(_begin_time), m_end(0) +{ + +} + +Event::Event(timestamp_t _begin_time, timestamp_t _end_time) : m_begin(_begin_time), m_end(_end_time) +{ + +} + BaseBlockData::BaseBlockData(timestamp_t _begin_time, block_id_t _descriptor_id) - : m_begin(_begin_time) - , m_end(0) + : Event(_begin_time) , m_id(_descriptor_id) { } BaseBlockData::BaseBlockData(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _descriptor_id) - : m_begin(_begin_time) - , m_end(_end_time) + : Event(_begin_time, _end_time) , m_id(_descriptor_id) { @@ -133,9 +141,25 @@ Block::~Block() ::profiler::endBlock(); } #else +Event::Event(timestamp_t) : m_begin(0), m_end(0) +{ + +} + +Event::Event(timestamp_t, timestamp_t) : m_begin(0), m_end(0) +{ + +} + BaseBlockData::BaseBlockData(timestamp_t, block_id_t) - : m_begin(0) - , m_end(0) + : Event(0, 0) + , m_id(~0U) +{ + +} + +BaseBlockData::BaseBlockData(timestamp_t, timestamp_t, block_id_t) + : Event(0, 0) , m_id(~0U) { @@ -199,16 +223,16 @@ Block::~Block() ////////////////////////////////////////////////////////////////////////// -CSwitchBlock::CSwitchBlock(timestamp_t _begin_time, thread_id_t _tid, const char* _runtimeName) - : Block(_begin_time, _begin_time, 0, _runtimeName) +CSwitchEvent::CSwitchEvent(timestamp_t _begin_time, thread_id_t _tid) + : Event(_begin_time) , m_thread_id(_tid) { } -CSwitchBlock::CSwitchBlock(CSwitchBlock&& _that) - : Block(std::forward(_that)) - , m_thread_id(_that.m_thread_id) +CSwitchBlock::CSwitchBlock(timestamp_t _begin_time, thread_id_t _tid, const char* _runtimeName) + : CSwitchEvent(_begin_time, _tid) + , m_name(_runtimeName) { } diff --git a/easy_profiler_core/include/easy/profiler.h b/easy_profiler_core/include/easy/profiler.h index 4fca4ea..cc3a8e2 100644 --- a/easy_profiler_core/include/easy/profiler.h +++ b/easy_profiler_core/include/easy/profiler.h @@ -493,7 +493,7 @@ namespace profiler { //*********************************************** - class PROFILER_API BaseBlockData + class PROFILER_API Event { friend ::ProfileManager; @@ -501,7 +501,30 @@ namespace profiler { timestamp_t m_begin; timestamp_t m_end; - block_id_t m_id; + + public: + + Event(const Event&) = default; + Event(timestamp_t _begin_time); + Event(timestamp_t _begin_time, timestamp_t _end_time); + + inline timestamp_t begin() const { return m_begin; } + inline timestamp_t end() const { return m_end; } + inline timestamp_t duration() const { return m_end - m_begin; } + + private: + + Event() = delete; + + }; // END class Event. + + class PROFILER_API BaseBlockData : public Event + { + friend ::ProfileManager; + + protected: + + block_id_t m_id; public: @@ -509,11 +532,7 @@ namespace profiler { BaseBlockData(timestamp_t _begin_time, block_id_t _id); BaseBlockData(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _id); - inline timestamp_t begin() const { return m_begin; } - inline timestamp_t end() const { return m_end; } inline block_id_t id() const { return m_id; } - inline timestamp_t duration() const { return m_end - m_begin; } - inline void setId(block_id_t _id) { m_id = _id; } private: @@ -521,6 +540,20 @@ namespace profiler { BaseBlockData() = delete; }; // END of class BaseBlockData. + + class PROFILER_API CSwitchEvent : public Event + { + thread_id_t m_thread_id; + + public: + + CSwitchEvent() = default; + CSwitchEvent(const CSwitchEvent&) = default; + CSwitchEvent(timestamp_t _begin_time, thread_id_t _tid); + + inline thread_id_t tid() const { return m_thread_id; } + + }; // END of class CSwitchEvent. #pragma pack(pop) //*********************************************** diff --git a/easy_profiler_core/include/easy/reader.h b/easy_profiler_core/include/easy/reader.h index f816e4b..25d905d 100644 --- a/easy_profiler_core/include/easy/reader.h +++ b/easy_profiler_core/include/easy/reader.h @@ -121,7 +121,12 @@ namespace profiler { 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.) + + union { + ::profiler::SerializedBlock* node; ///< Pointer to serilized data for regular block (id, name, begin, end etc.) + ::profiler::SerializedCSwitch* cs; ///< Pointer to serilized data for context switch (thread_id, 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 diff --git a/easy_profiler_core/include/easy/serialized_block.h b/easy_profiler_core/include/easy/serialized_block.h index 188c629..69e0d40 100644 --- a/easy_profiler_core/include/easy/serialized_block.h +++ b/easy_profiler_core/include/easy/serialized_block.h @@ -51,7 +51,7 @@ namespace profiler { ////////////////////////////////////////////////////////////////////////// - class PROFILER_API SerializedBlock : public BaseBlockData + class PROFILER_API SerializedBlock EASY_FINAL : public BaseBlockData { friend ::ProfileManager; friend ::ThreadStorage; @@ -63,68 +63,43 @@ namespace profiler { ///< Run-time block name is stored right after main BaseBlockData data inline const char* name() const { return data() + sizeof(BaseBlockData); } - protected: + private: - SerializedBlock(const ::profiler::Block& block, uint16_t name_length); + SerializedBlock(const Block& block, uint16_t name_length); SerializedBlock(const SerializedBlock&) = delete; SerializedBlock& operator = (const SerializedBlock&) = delete; - - //TODO yse: reason of deleted - //~SerializedBlock() = delete; - - protected: - - SerializedBlock(const ::profiler::Block& block); + ~SerializedBlock() = delete; }; // END of SerializedBlock. ////////////////////////////////////////////////////////////////////////// -#pragma pack(push, 1) - - /** This is serious work-around to be able to read/write valid - thread ids after changing thread_id_t from 32-bit to 64-bit. - - Before v1.3.0 thread_id_t was uint32_t and has been stored in BaseBlockData::m_id. - After v1.3.0 we have to allocate additional 4 bytes per context switch block to - be able to store 64-bit value. - - This is bad design decision at first look, but it has backward compatibility, - does not require serious changes to Core API (except this particular class) - and saves 4 bytes per context switch block. - - TODO: think about better solution. - */ - class PROFILER_API SerializedCSwitch : public SerializedBlock + class PROFILER_API SerializedCSwitch EASY_FINAL : public CSwitchEvent { friend ::ProfileManager; friend ::ThreadStorage; - uint32_t m_reserve; /** Additional 4 bytes used to store second part of thread_id_t - (first part is stored in BaseBlockData::m_id as it was before - changing thread_id_t to 64-bit) */ - public: - ///< Thread id is stored in m_id + m_reserve - inline thread_id_t tid() const { return *reinterpret_cast(&m_id); } + inline const char* data() const { return reinterpret_cast(this); } - ///< Run-time block name is stored right after main BaseBlockData data and reserved 4 bytes block - inline const char* name() const { return data() + sizeof(BaseBlockData) + 4; } + ///< Run-time block name is stored right after main CSwitchEvent data + inline const char* name() const { return data() + sizeof(CSwitchEvent); } private: SerializedCSwitch(const CSwitchBlock& block, uint16_t name_length); - SerializedCSwitch(const SerializedBlock&) = delete; - SerializedCSwitch& operator = (const SerializedBlock&) = delete; + SerializedCSwitch(const SerializedCSwitch&) = delete; + SerializedCSwitch& operator = (const SerializedCSwitch&) = delete; ~SerializedCSwitch() = delete; }; // END of SerializedCSwitch. ////////////////////////////////////////////////////////////////////////// +#pragma pack(push, 1) class PROFILER_API SerializedBlockDescriptor EASY_FINAL : public BaseBlockDescriptor { uint16_t m_nameLength; ///< Length of the name including trailing '\0' sybmol diff --git a/easy_profiler_core/profile_manager.cpp b/easy_profiler_core/profile_manager.cpp index bb0065c..2c62d5f 100644 --- a/easy_profiler_core/profile_manager.cpp +++ b/easy_profiler_core/profile_manager.cpp @@ -519,17 +519,9 @@ SerializedBlock::SerializedBlock(const Block& block, uint16_t name_length) pName[name_length] = 0; } -SerializedBlock::SerializedBlock(const Block& block) - : BaseBlockData(block) -{ - -} - SerializedCSwitch::SerializedCSwitch(const CSwitchBlock& block, uint16_t name_length) - : SerializedBlock(block) + : CSwitchEvent(block) { - *reinterpret_cast(&m_id) = block.tid(); - auto pName = const_cast(name()); if (name_length) strncpy(pName, block.name(), name_length); pName[name_length] = 0; @@ -681,7 +673,7 @@ void ThreadStorage::storeBlock(const profiler::Block& block) void ThreadStorage::storeCSwitch(const CSwitchBlock& block) { auto name_length = static_cast(strlen(block.name())); - auto size = static_cast(sizeof(BaseBlockData) + name_length + 5); + auto size = static_cast(sizeof(CSwitchEvent) + name_length + 1); auto data = sync.closedList.allocate(size); ::new (data) SerializedCSwitch(block, name_length); sync.usedMemorySize += size; diff --git a/easy_profiler_core/profile_manager.h b/easy_profiler_core/profile_manager.h index af1f6b2..6e90277 100644 --- a/easy_profiler_core/profile_manager.h +++ b/easy_profiler_core/profile_manager.h @@ -421,29 +421,20 @@ struct BlocksList ////////////////////////////////////////////////////////////////////////// -class CSwitchBlock : public ::profiler::Block +class CSwitchBlock : public profiler::CSwitchEvent { - ::profiler::thread_id_t m_thread_id; + const char* m_name; public: - CSwitchBlock(::profiler::timestamp_t _begin_time, ::profiler::thread_id_t _tid, const char* _runtimeName); - CSwitchBlock(CSwitchBlock&& _that); - - inline ::profiler::thread_id_t tid() const { - return m_thread_id; - } - -private: - - CSwitchBlock(const CSwitchBlock&) = delete; - CSwitchBlock& operator = (const CSwitchBlock&) = delete; + CSwitchBlock(profiler::timestamp_t _begin_time, profiler::thread_id_t _tid, const char* _runtimeName); + inline const char* name() const { return m_name; } }; ////////////////////////////////////////////////////////////////////////// const uint16_t SIZEOF_BLOCK = sizeof(profiler::BaseBlockData) + 1 + sizeof(uint16_t); // SerializedBlock stores BaseBlockData + at least 1 character for name ('\0') + 2 bytes for size of serialized data -const uint16_t SIZEOF_CSWITCH = SIZEOF_BLOCK + 4; // SerializedCSwitch also stores additional 4 bytes to be able to save 64-bit thread_id +const uint16_t SIZEOF_CSWITCH = sizeof(profiler::CSwitchEvent) + 1 + sizeof(uint16_t); // SerializedCSwitch also stores additional 4 bytes to be able to save 64-bit thread_id struct ThreadStorage { diff --git a/easy_profiler_core/reader.cpp b/easy_profiler_core/reader.cpp index 355d78d..314424d 100644 --- a/easy_profiler_core/reader.cpp +++ b/easy_profiler_core/reader.cpp @@ -609,7 +609,7 @@ extern "C" { char* data = serialized_blocks[i]; inFile.read(data, sz); i += sz; - auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); + auto baseData = reinterpret_cast<::profiler::SerializedCSwitch*>(data); auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); auto t_end = t_begin + 1; @@ -626,7 +626,7 @@ extern "C" { blocks.emplace_back(); ::profiler::BlocksTree& tree = blocks.back(); - tree.node = baseData; + tree.cs = baseData; const auto block_index = blocks_counter++; root.wait_time += baseData->duration(); diff --git a/profiler_gui/blocks_graphics_view.cpp b/profiler_gui/blocks_graphics_view.cpp index e8f3a1f..2cbc028 100644 --- a/profiler_gui/blocks_graphics_view.cpp +++ b/profiler_gui/blocks_graphics_view.cpp @@ -1711,7 +1711,19 @@ void EasyGraphicsView::onIdleTimeout() lay->addWidget(new QLabel("Thread:", widget), row, 0, Qt::AlignRight); - const ::profiler::thread_id_t tid = EASY_GLOBALS.version < ::profiler_gui::V130 ? cse->tree.node->id() : static_cast(cse->tree.node)->tid(); + const char* process_name = ""; + ::profiler::thread_id_t tid = 0; + if (EASY_GLOBALS.version < ::profiler_gui::V130) + { + tid = cse->tree.node->id(); + process_name = cse->tree.node->name(); + } + else + { + tid = cse->tree.cs->tid(); + process_name = cse->tree.cs->name(); + } + auto it = EASY_GLOBALS.profiler_blocks.find(tid); if (it != EASY_GLOBALS.profiler_blocks.end()) @@ -1728,7 +1740,7 @@ void EasyGraphicsView::onIdleTimeout() ++row; lay->addWidget(new QLabel("Process:", widget), row, 0, Qt::AlignRight); - lay->addWidget(new QLabel(cse->tree.node->name(), widget), row, 1, 1, 2, Qt::AlignLeft); + lay->addWidget(new QLabel(process_name, widget), row, 1, 1, 2, Qt::AlignLeft); ++row; const auto duration = itemBlock.node->duration(); @@ -2139,10 +2151,7 @@ void EasyThreadNamesWidget::removePopup(bool _removeFromScene) delete widget; if (_removeFromScene) - { scene()->removeItem(m_popupWidget); - setFixedWidth(m_maxLength); - } m_popupWidget = nullptr; } @@ -2221,22 +2230,38 @@ void EasyThreadNamesWidget::onIdleTimeout() auto scenePos = mapToScene(mapFromGlobal(QCursor::pos())); if (scenePos.x() < visibleSceneRect.left() || scenePos.x() > visibleSceneRect.right()) + { + if (m_idleTime > 3000) + setFixedWidth(m_maxLength); return; + } if (scenePos.y() < visibleSceneRect.top() || scenePos.y() > visibleSceneRect.bottom()) + { + if (m_idleTime > 3000) + setFixedWidth(m_maxLength); return; + } auto const parentView = static_cast(scene()->parent()); const auto view = parentView->view(); if (scenePos.y() > view->visibleSceneRect().bottom()) + { + if (m_idleTime > 3000) + setFixedWidth(m_maxLength); return; + } const qreal y = scenePos.y() - visibleSceneRect.top(); const auto& items = view->getItems(); if (items.empty()) + { + if (m_idleTime > 3000) + setFixedWidth(m_maxLength); return; + } EasyGraphicsItem* intersectingItem = nullptr; for (auto item : items) @@ -2332,7 +2357,7 @@ void EasyThreadNamesWidget::onIdleTimeout() auto br = m_popupWidget->boundingRect(); - if (m_maxLength < br.width()) + if (maximumWidth() < br.width()) { setFixedWidth(static_cast(br.width())); visibleSceneRect.setWidth(br.width()); diff --git a/profiler_gui/easy_graphics_item.cpp b/profiler_gui/easy_graphics_item.cpp index ab2638f..1aab802 100644 --- a/profiler_gui/easy_graphics_item.cpp +++ b/profiler_gui/easy_graphics_item.cpp @@ -1013,7 +1013,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* if (width < MIN_SYNC_SIZE) width = MIN_SYNC_SIZE; - const ::profiler::thread_id_t tid = EASY_GLOBALS.version < ::profiler_gui::V130 ? item.node->id() : static_cast(item.node)->tid(); + const ::profiler::thread_id_t tid = EASY_GLOBALS.version < ::profiler_gui::V130 ? item.node->id() : item.cs->tid(); const bool self_thread = tid != 0 && EASY_GLOBALS.profiler_blocks.find(tid) != EASY_GLOBALS.profiler_blocks.end(); ::profiler::color_t color = 0;