From 6cc4de8d2834a27a26152fcc5ed1787c2b5f3ecc Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 29 Feb 2020 16:24:15 +0100 Subject: [PATCH] Construct parent call stacks for sampled stack traces. --- server/TracyEvent.hpp | 3 +- server/TracyWorker.cpp | 90 ++++++++++++++++++++++++++++++++++++++---- server/TracyWorker.hpp | 6 ++- 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index dd2efa79..abd72b26 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -354,8 +354,9 @@ union CallstackFrameId { struct { - uint64_t idx : 63; + uint64_t idx : 62; uint64_t sel : 1; + uint64_t custom : 1; }; uint64_t data; }; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 2c3e01a5..42b8c3aa 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -30,10 +30,11 @@ namespace tracy static inline CallstackFrameId PackPointer( uint64_t ptr ) { - assert( ( ( ptr & 0x4000000000000000 ) << 1 ) == ( ptr & 0x8000000000000000 ) ); + assert( ( ( ptr & 0x3000000000000000 ) << 2 ) == ( ptr & 0xC000000000000000 ) ); CallstackFrameId id; id.idx = ptr; id.sel = 0; + id.custom = 0; return id; } @@ -3123,7 +3124,7 @@ void Worker::AddFrameImageData( uint64_t ptr, const char* data, size_t sz ) uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const { assert( id.sel == 0 ); - return ( id.idx & 0x7FFFFFFFFFFFFFFF ) | ( ( id.idx & 0x4000000000000000 ) << 1 ); + return ( id.idx & 0x3FFFFFFFFFFFFFFF ) | ( ( id.idx & 0xC000000000000000 ) << 2 ); } void Worker::AddCallstackPayload( uint64_t ptr, const char* _data, size_t _sz ) @@ -3201,6 +3202,7 @@ void Worker::AddCallstackAllocPayload( uint64_t ptr, const char* data, size_t _s frameData->size = 1; id.idx = m_callstackAllocNextIdx++; id.sel = 1; + id.custom = 0; m_data.callstackFrameMap.emplace( id, frameData ); m_data.revFrameMap.emplace( frameData, id ); } @@ -5304,7 +5306,7 @@ void Worker::UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool ca } } - UpdateSampleStatisticsImpl( frames, cssz, count ); + UpdateSampleStatisticsImpl( frames, cssz, count, cs ); } void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it ) @@ -5324,20 +5326,20 @@ void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postpo frames[i] = frame; } - UpdateSampleStatisticsImpl( frames, cssz, it->second ); + UpdateSampleStatisticsImpl( frames, cssz, it->second, cs ); it = m_data.postponedSamples.erase( it ); } -void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count ) +void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count, const VarArray& cs ) { + const auto fexcl = frames[0]; + const auto fxsz = fexcl->size; { - const auto fexcl = frames[0]; - 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 ); @@ -5357,6 +5359,78 @@ void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint sym->second.incl += count; } } + + CallstackFrameId parentFrameId; + if( fxsz != 1 ) + { + auto cfdata = (CallstackFrame*)alloca( ( fxsz-1 ) * sizeof( CallstackFrame ) ); + for( int i=0; idata[i+1]; + } + CallstackFrameData cfd; + cfd.data = cfdata; + cfd.size = fxsz-1; + cfd.imageName = fexcl->imageName; + + auto it = m_data.revParentFrameMap.find( &cfd ); + if( it == m_data.revParentFrameMap.end() ) + { + auto frame = m_slab.Alloc( fxsz-1 ); + memcpy( frame, cfdata, fxsz * sizeof( CallstackFrame ) ); + auto frameData = m_slab.AllocInit(); + frameData->data = frame; + frameData->size = fxsz - 1; + parentFrameId.idx = m_callstackParentNextIdx++; + parentFrameId.sel = 0; + parentFrameId.custom = 1; + m_data.callstackFrameMap.emplace( parentFrameId, frameData ); + m_data.revParentFrameMap.emplace( frameData, parentFrameId ); + } + else + { + parentFrameId = it->second; + } + } + + const auto sz = framesCount - ( fxsz == 1 ); + const auto memsize = sizeof( VarArray ) + sz * sizeof( CallstackFrameId ); + auto mem = (char*)m_slab.AllocRaw( memsize ); + + auto data = (CallstackFrameId*)mem; + auto dst = data; + if( fxsz == 1 ) + { + for( int i=0; i*)( mem + sz * sizeof( CallstackFrameId ) ); + new(arr) VarArray( sz, data ); + + uint32_t idx; + auto it = m_data.parentCallstackMap.find( arr ); + if( it == m_data.parentCallstackMap.end() ) + { + idx = m_data.parentCallstackPayload.size(); + m_data.parentCallstackMap.emplace( arr, idx ); + m_data.parentCallstackPayload.push_back( arr ); + } + else + { + idx = it->second; + m_slab.Unalloc( memsize ); + } } #endif diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 773a15eb..335ae285 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -227,6 +227,9 @@ private: unordered_flat_map symbolStats; #ifndef TRACY_NO_STATISTICS + unordered_flat_map*, uint32_t, VarArrayHasher, VarArrayComparator> parentCallstackMap; + Vector>> parentCallstackPayload; + unordered_flat_map revParentFrameMap; unordered_flat_map postponedSamples; bool newFramesWereReceived = false; bool callstackSamplesReady = false; @@ -643,7 +646,7 @@ private: void ReconstructContextSwitchUsage(); void UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool canPostpone ); void UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it ); - void UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count ); + void UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count, const VarArray& cs ); #endif tracy_force_inline int64_t ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx ); @@ -731,6 +734,7 @@ private: CallstackFrameData* m_callstackFrameStaging; uint64_t m_callstackFrameStagingPtr; uint64_t m_callstackAllocNextIdx = 0; + uint64_t m_callstackParentNextIdx = 0; uint64_t m_lastMemActionCallstack; bool m_lastMemActionWasAlloc;