diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index fd7aa189..480ab970 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -2450,6 +2450,13 @@ void Profiler::CalibrateDelay() void Profiler::ReportTopology() { + struct CpuData + { + uint32_t package; + uint32_t core; + uint32_t thread; + }; + #if defined _WIN32 || defined __CYGWIN__ # ifdef UNICODE t_GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx = (t_GetLogicalProcessorInformationEx)GetProcAddress( GetModuleHandle( L"kernel32" ), "GetLogicalProcessorInformationEx" ); @@ -2475,13 +2482,6 @@ void Profiler::ReportTopology() GetSystemInfo( &sysinfo ); const uint32_t numcpus = sysinfo.dwNumberOfProcessors; - struct CpuData - { - uint32_t package; - uint32_t core; - uint32_t thread; - }; - auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus ); for( uint32_t i=0; iget_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::CpuTopology ); + MemWrite( &item->cpuTopology.package, data.package ); + MemWrite( &item->cpuTopology.core, data.core ); + MemWrite( &item->cpuTopology.thread, data.thread ); + +#ifdef TRACY_ON_DEMAND + DeferItem( *item ); +#endif + + tail.store( magic + 1, std::memory_order_release ); + } + tracy_free( cpuData ); tracy_free( coreInfo ); tracy_free( packageInfo ); diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index 37dfa1fe..aab0ad77 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -9,7 +9,7 @@ namespace tracy constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; } -enum : uint32_t { ProtocolVersion = 24 }; +enum : uint32_t { ProtocolVersion = 25 }; enum : uint32_t { BroadcastVersion = 0 }; using lz4sz_t = uint32_t; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index e38f7272..a1b7d7a7 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -68,6 +68,7 @@ enum class QueueType : uint8_t TidToPid, PlotConfig, ParamSetup, + CpuTopology, StringData, ThreadName, CustomStringData, @@ -357,6 +358,13 @@ struct QueueParamSetup int32_t val; }; +struct QueueCpuTopology +{ + uint32_t package; + uint32_t core; + uint32_t thread; +}; + struct QueueHeader { union @@ -407,6 +415,7 @@ struct QueueItem QueueTidToPid tidToPid; QueuePlotConfig plotConfig; QueueParamSetup paramSetup; + QueueCpuTopology cpuTopology; }; }; #pragma pack() @@ -476,6 +485,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueTidToPid ), sizeof( QueueHeader ) + sizeof( QueuePlotConfig ), sizeof( QueueHeader ) + sizeof( QueueParamSetup ), + sizeof( QueueHeader ) + sizeof( QueueCpuTopology ), // keep all QueueStringTransfer below sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name diff --git a/server/TracyVersion.hpp b/server/TracyVersion.hpp index 5213979f..6b081aa5 100644 --- a/server/TracyVersion.hpp +++ b/server/TracyVersion.hpp @@ -7,7 +7,7 @@ namespace Version { enum { Major = 0 }; enum { Minor = 6 }; -enum { Patch = 1 }; +enum { Patch = 2 }; } } diff --git a/server/TracyView.cpp b/server/TracyView.cpp index fed9c9ab..88fa1e08 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -11390,6 +11390,59 @@ void View::DrawInfo() ImGui::TreePop(); } + auto& topology = m_worker.GetCpuTopology(); + if( !topology.empty() ) + { + if( ImGui::TreeNode( "CPU topology" ) ) + { + std::vector tsort; + tsort.reserve( topology.size() ); + for( auto it = topology.begin(); it != topology.end(); ++it ) tsort.emplace_back( it ); + std::sort( tsort.begin(), tsort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } ); + char buf[128]; + for( auto& package : tsort ) + { +#ifdef TRACY_EXTENDED_FONT + sprintf( buf, ICON_FA_BOX " Package %i", package->first ); +#else + sprintf( buf, "Package %i", package->first ); +#endif + if( ImGui::TreeNodeEx( buf, ImGuiTreeNodeFlags_DefaultOpen ) ) + { + std::vectorsecond.begin())> csort; + csort.reserve( package->second.size() ); + for( auto it = package->second.begin(); it != package->second.end(); ++it ) csort.emplace_back( it ); + std::sort( csort.begin(), csort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } ); + for( auto& core : csort ) + { +#ifdef TRACY_EXTENDED_FONT + sprintf( buf, ICON_FA_MICROCHIP " Core %i", core->first ); +#else + sprintf( buf, "Core %i", core->first ); +#endif + if( ImGui::TreeNodeEx( buf, ImGuiTreeNodeFlags_DefaultOpen ) ) + { + ImGui::Indent(); + for( auto& thread : core->second ) + { +#ifdef TRACY_EXTENDED_FONT + sprintf( buf, ICON_FA_RANDOM " Thread %i", thread ); +#else + sprintf( buf, "Thread %i", thread ); +#endif + ImGui::TextUnformatted( buf ); + } + ImGui::Unindent(); + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } + } + ImGui::Separator(); TextFocused( "PID:", RealToString( m_worker.GetPid(), true ) ); TextFocused( "Host info:", m_worker.GetHostInfo().c_str() ); diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index a784cfeb..6aab6260 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -343,6 +343,34 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) m_hostInfo = std::string( tmp, tmp+sz ); } + if( fileVer >= FileVersion( 0, 6, 2 ) ) + { + f.Read( sz ); + m_data.cpuTopology.reserve( sz ); + for( uint64_t i=0; i> {} ).first; + package.second.reserve( psz ); + for( uint64_t j=0; j {} ).first; + core.second.reserve( csz ); + for( uint64_t k=0; k> {} ).first; + auto core = package->second.find( ev.core ); + if( core == package->second.end() ) core = package->second.emplace( ev.core, std::vector {} ).first; + core->second.emplace_back( ev.thread ); +} + void Worker::MemAllocChanged( int64_t time ) { const auto val = (double)m_data.memory.usage; @@ -5171,6 +5211,25 @@ void Worker::Write( FileWrite& f ) f.Write( &sz, sizeof( sz ) ); f.Write( m_hostInfo.c_str(), sz ); + sz = m_data.cpuTopology.size(); + f.Write( &sz, sizeof( sz ) ); + for( auto& package : m_data.cpuTopology ) + { + sz = package.second.size(); + f.Write( &package.first, sizeof( package.first ) ); + f.Write( &sz, sizeof( sz ) ); + for( auto& core : package.second ) + { + sz = core.second.size(); + f.Write( &core.first, sizeof( core.first ) ); + f.Write( &sz, sizeof( sz ) ); + for( auto& thread : core.second ) + { + f.Write( &thread, sizeof( thread ) ); + } + } + } + f.Write( &m_data.crashEvent, sizeof( m_data.crashEvent ) ); sz = m_data.frames.Data().size(); diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 32d25c6a..e808c419 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -228,6 +228,8 @@ private: Vector ctxUsage; bool ctxUsageReady = false; #endif + + flat_hash_map>> cpuTopology; }; struct MbpsBlock @@ -422,6 +424,8 @@ public: const Vector& GetParameters() const { return m_params; } void SetParameter( size_t paramIdx, int32_t val ); + const decltype(DataBlock::cpuTopology)& GetCpuTopology() const { return m_data.cpuTopology; } + private: void Network(); void Exec(); @@ -483,6 +487,7 @@ private: tracy_force_inline void ProcessThreadWakeup( const QueueThreadWakeup& ev ); tracy_force_inline void ProcessTidToPid( const QueueTidToPid& ev ); tracy_force_inline void ProcessParamSetup( const QueueParamSetup& ev ); + tracy_force_inline void ProcessCpuTopology( const QueueCpuTopology& ev ); tracy_force_inline ZoneEvent* AllocZoneEvent(); tracy_force_inline void ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev );