From 852e37c8ddeb69da1a0adec4461ad77686dffe26 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Thu, 27 Feb 2020 01:22:36 +0100 Subject: [PATCH] Calculate callstack sample data on trace load. --- server/TracyEvent.hpp | 8 +++++ server/TracyWorker.cpp | 72 +++++++++++++++++++++++++++++++++++++++++- server/TracyWorker.hpp | 6 ++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index fb8436bd..9a9daf2a 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -660,6 +660,14 @@ struct Parameter int32_t val; }; + +struct SymbolStats +{ + uint32_t incl, excl; +}; + +enum { SymbolStatsSize = sizeof( SymbolStats ) }; + } #endif diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 16a0fd4a..b130ddf5 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -244,6 +244,7 @@ Worker::Worker( const char* addr, int port ) #ifndef TRACY_NO_STATISTICS m_data.sourceLocationZonesReady = true; + m_data.callstackSamplesReady = false; // FIXME implement live data update m_data.ctxUsageReady = true; #endif @@ -1660,7 +1661,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) { m_backgroundDone.store( false, std::memory_order_relaxed ); #ifndef TRACY_NO_STATISTICS - m_threadBackground = std::thread( [this, reconstructMemAllocPlot] { + m_threadBackground = std::thread( [this, reconstructMemAllocPlot, eventMask] { if( !m_data.ctxSwitch.empty() ) { ReconstructContextSwitchUsage(); @@ -1710,6 +1711,75 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) m_data.sourceLocationZonesReady = true; } + if( eventMask & EventType::Samples ) + { + unordered_flat_map counts; + uint32_t total = 0; + for( auto& t : m_data.threads ) total += t->samples.size(); + if( total != 0 ) + { + counts.reserve( total ); + for( auto& t : m_data.threads ) + { + if( m_shutdown.load( std::memory_order_relaxed ) ) return; + for( auto& sd : t->samples ) + { + const auto cs = sd.callstack.Val(); + auto it = counts.find( cs ); + if( it == counts.end() ) + { + counts.emplace( cs, 1 ); + } + else + { + it->second++; + } + } + } + for( auto& v : counts ) + { + const auto count = v.second; + const auto& cs = GetCallstack( v.first ); + const auto cssz = cs.size(); + + const auto fexcl = GetCallstackFrame( cs[0] ); + if( fexcl ) + { + const auto fsz = fexcl->size; + const auto& frame0 = fexcl->data[0]; + auto sym = m_data.symbolStats.find( frame0.symAddr ); + if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame0.symAddr, SymbolStats {} ).first; + sym->second.excl += count; + for( uint8_t f=1; fdata[f]; + sym = m_data.symbolStats.find( frame.symAddr ); + if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame.symAddr, SymbolStats {} ).first; + sym->second.incl += count; + } + } + for( uint8_t c=1; csize; + for( uint8_t f=0; fdata[f]; + auto sym = m_data.symbolStats.find( frame.symAddr ); + if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame.symAddr, SymbolStats {} ).first; + sym->second.incl += count; + } + } + } + } + } + + std::lock_guard lock( m_data.lock ); + m_data.callstackSamplesReady = true; + } + m_backgroundDone.store( true, std::memory_order_relaxed ); } ); #else diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index d9544cfb..efcc6840 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -215,6 +215,11 @@ private: unordered_flat_map callstackFrameMap; unordered_flat_map revFrameMap; unordered_flat_map symbolMap; + unordered_flat_map symbolStats; + +#ifndef TRACY_NO_STATISTICS + bool callstackSamplesReady = false; +#endif unordered_flat_map lockMap; @@ -420,6 +425,7 @@ public: const unordered_flat_map& GetSourceLocationZones() const { return m_data.sourceLocationZones; } bool AreSourceLocationZonesReady() const { return m_data.sourceLocationZonesReady; } bool IsCpuUsageReady() const { return m_data.ctxUsageReady; } + bool AreCallstackSamplesReady() const { return m_data.callstackSamplesReady; } #endif tracy_force_inline uint16_t CompressThread( uint64_t thread ) { return m_data.localThreadCompress.CompressThread( thread ); }