diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index a4f8f3eb..55313d3d 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -500,6 +500,16 @@ struct FrameImage enum { FrameImageSize = sizeof( FrameImage ) }; + +struct GhostZone +{ + Int48 start, end; + CallstackFrameId frame; + int32_t child; +}; + +enum { GhostZoneSize = sizeof( GhostZone ) }; + #pragma pack() @@ -514,6 +524,7 @@ struct ThreadData Vector zoneIdStack; #ifndef TRACY_NO_STATISTICS Vector childTimeStack; + Vector ghostZones; #endif Vector samples; }; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index d8fb7817..948d5f44 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -242,6 +242,7 @@ Worker::Worker( const char* addr, int port ) #ifndef TRACY_NO_STATISTICS m_data.sourceLocationZonesReady = true; m_data.callstackSamplesReady = true; + m_data.ghostZonesReady = true; m_data.ctxUsageReady = true; #endif @@ -1743,8 +1744,70 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) for( auto& v : counts ) UpdateSampleStatistics( v.first, v.second, false ); } + { + std::lock_guard lock( m_data.lock ); + m_data.callstackSamplesReady = true; + } + + uint32_t gcnt = 0; + for( auto& t : m_data.threads ) + { + if( m_shutdown.load( std::memory_order_relaxed ) ) return; + for( auto& sd : t->samples ) + { + const auto& cs = GetCallstack( sd.callstack.Val() ); + const auto time = sd.time.Val(); + auto vec = &t->ghostZones; + + auto idx = cs.size() - 1; + do + { + auto& entry = cs[idx]; + if( vec->empty() ) + { + gcnt++; + auto& zone = vec->push_next(); + zone.start.SetVal( time ); + zone.end.SetVal( time + m_samplingPeriod ); + zone.frame = entry; + zone.child = -1; + } + else if( vec->back().frame == entry ) + { + auto& zone = vec->back(); + zone.end.SetVal( time + m_samplingPeriod ); + } + else + { + gcnt++; + vec->back().end.SetVal( time ); + auto& zone = vec->push_next(); + zone.start.SetVal( time ); + zone.end.SetVal( time + m_samplingPeriod ); + zone.frame = entry; + zone.child = -1; + } + if( idx > 0 ) + { + auto& zone = vec->back(); + if( zone.child < 0 ) + { + zone.child = m_data.ghostChildren.size(); + vec = &m_data.ghostChildren.push_next(); + } + else + { + vec = &m_data.ghostChildren[zone.child]; + } + } + } + while( idx-- > 0 ); + } + } + std::lock_guard lock( m_data.lock ); - m_data.callstackSamplesReady = true; + m_data.ghostZonesReady = true; + m_data.ghostCnt = gcnt; } m_backgroundDone.store( true, std::memory_order_relaxed ); @@ -1781,6 +1844,7 @@ Worker::~Worker() v->samples.~Vector(); #ifndef TRACY_NO_STATISTICS v->childTimeStack.~Vector(); + v->ghostZones.~Vector(); #endif } for( auto& v : m_data.gpuData ) @@ -1803,6 +1867,12 @@ Worker::~Worker() { v.second->~LockMap(); } +#ifndef TRACY_NO_STATISTICS + for( auto& v : m_data.ghostChildren ) + { + v.~Vector(); + } +#endif } uint64_t Worker::GetLockCount() const diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 554adf2b..c12cd176 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -196,6 +196,7 @@ private: uint64_t zonesCnt = 0; uint64_t gpuCnt = 0; uint64_t samplesCnt = 0; + uint64_t ghostCnt = 0; int64_t baseTime = 0; int64_t lastTime = 0; uint64_t frameOffset = 0; @@ -232,6 +233,7 @@ private: unordered_flat_map postponedSamples; bool newFramesWereReceived = false; bool callstackSamplesReady = false; + bool ghostZonesReady = false; #endif unordered_flat_map lockMap; @@ -241,6 +243,9 @@ private: Vector>> zoneChildren; Vector>> gpuChildren; +#ifndef TRACY_NO_STATISTICS + Vector> ghostChildren; +#endif Vector>> zoneVectorCache; @@ -368,6 +373,7 @@ public: uint64_t GetCallstackFrameCount() const { return m_data.callstackFrameMap.size(); } uint64_t GetCallstackSampleCount() const { return m_data.samplesCnt; } uint64_t GetSymbolsCount() const { return m_data.symbolMap.size(); } + uint64_t GetGhostZonesCount() const { return m_data.ghostCnt; } uint32_t GetFrameImageCount() const { return (uint32_t)m_data.frameImage.size(); } uint64_t GetStringsCount() const { return m_data.strings.size() + m_data.stringData.size(); } uint64_t GetFrameOffset() const { return m_data.frameOffset; } @@ -437,6 +443,9 @@ public: tracy_force_inline const Vector>& GetZoneChildren( int32_t idx ) const { return m_data.zoneChildren[idx]; } tracy_force_inline const Vector>& GetGpuChildren( int32_t idx ) const { return m_data.gpuChildren[idx]; } +#ifndef TRACY_NO_STATISTICS + tracy_force_inline const Vector& GetGhostChildren( int32_t idx ) const { return m_data.ghostChildren[idx]; } +#endif tracy_force_inline const bool HasZoneExtra( const ZoneEvent& ev ) const { return ev.extra != 0; } tracy_force_inline const ZoneExtra& GetZoneExtra( const ZoneEvent& ev ) const { return m_data.zoneExtra[ev.extra]; }