From 0cdb6d365e417264826944d2ecdffaf099f669a5 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 17 Jun 2026 17:50:20 +0200 Subject: [PATCH] Initial section enter / leave instrumentation. --- public/client/TracyProfiler.cpp | 25 +++++++++++++++++++ public/client/TracyProfiler.hpp | 43 +++++++++++++++++++++++++++++++++ public/common/TracyProtocol.hpp | 2 +- public/common/TracyQueue.hpp | 25 +++++++++++++++++++ public/tracy/Tracy.hpp | 6 +++++ server/TracyWorker.cpp | 15 ++++++++++++ server/TracyWorker.hpp | 2 ++ 7 files changed, 117 insertions(+), 1 deletion(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index ebcac690..dc46b081 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1521,6 +1521,7 @@ Profiler::Profiler() , m_noExit( false ) , m_userPort( 0 ) , m_zoneId( 1 ) + , m_sectionId( 1 ) , m_samplingPeriod( 0 ) , m_stream( LZ4_createStream() ) , m_buffer( (char*)tracy_malloc( TargetFrameSize*3 ) ) @@ -2484,6 +2485,10 @@ static void FreeAssociatedMemory( const QueueItem& item ) ptr = MemRead( &item.sourceCodeMetadata.ptr ); tracy_free( (void*)ptr ); break; + case QueueType::SectionEnter: + ptr = MemRead( &item.sectionEnterFat.text ); + tracy_free( (void*)ptr ); + break; default: break; } @@ -2863,6 +2868,26 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token ) ++item; continue; } + case QueueType::SectionEnter: + { + int64_t t = MemRead( &item->sectionEnter.time ); + int64_t dt = t - refThread; + refThread = t; + MemWrite( &item->sectionEnter.time, dt ); + ptr = MemRead( &item->sectionEnterFat.text ); + size = MemRead( &item->sectionEnterFat.size ); + SendSingleString( (const char*)ptr, size ); + tracy_free_fast( (void*)ptr ); + break; + } + case QueueType::SectionLeave: + { + int64_t t = MemRead( &item->sectionLeave.time ); + int64_t dt = t - refThread; + refThread = t; + MemWrite( &item->sectionLeave.time, dt ); + break; + } default: assert( false ); break; diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index ae9bb795..a9183289 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include "../common/TracyQueue.hpp" #include "../common/TracyAlign.hpp" #include "../common/TracyAlloc.hpp" +#include "../common/TracyFormat.hpp" #include "../common/TracyMutex.hpp" #include "../common/TracyProtocol.hpp" @@ -792,6 +794,46 @@ public: } #endif + static tracy_force_inline uint32_t SectionEnter( const char* fmt, ... ) TRACY_ATTRIBUTE_FORMAT_PRINTF( 1, 2 ) + { + auto& profiler = GetProfiler(); +#ifdef TRACY_ON_DEMAND + if( !profiler.IsConnected() ) return 0; +#endif + va_list args; + va_start( args, fmt ); + auto size = vsnprintf( nullptr, 0, fmt, args ); + va_end( args ); + if( size < 0 ) return 0; + assert( size < (std::numeric_limits::max)() ); + + char* ptr = (char*)tracy_malloc( size_t( size ) + 1 ); + va_start( args, fmt ); + vsnprintf( ptr, size_t( size ) + 1, fmt, args ); + va_end( args ); + + const auto id = profiler.m_sectionId.fetch_add( 1, std::memory_order_relaxed ); + TracyLfqPrepare( QueueType::SectionEnter ); + MemWrite( &item->sectionEnterFat.time, GetTime() ); + MemWrite( &item->sectionEnterFat.id, id ); + MemWrite( &item->sectionEnterFat.text, (uint64_t)ptr ); + MemWrite( &item->sectionEnterFat.size, (uint16_t)size ); + TracyLfqCommit; + return id; + } + + static tracy_force_inline void SectionLeave( uint32_t id ) + { + if( id == 0 ) return; +#ifdef TRACY_ON_DEMAND + if( !GetProfiler().IsConnected() ) return; +#endif + TracyLfqPrepare( QueueType::SectionLeave ); + MemWrite( &item->sectionLeave.time, GetTime() ); + MemWrite( &item->sectionLeave.id, id ); + TracyLfqCommit; + } + void SendCallstack( int32_t depth, const char** skipBefore ); static void CutCallstack( void* callstack, const char** skipBefore ); @@ -1064,6 +1106,7 @@ private: bool m_noExit; uint32_t m_userPort; std::atomic m_zoneId; + std::atomic m_sectionId; int64_t m_samplingPeriod; uint32_t m_threadCtx; diff --git a/public/common/TracyProtocol.hpp b/public/common/TracyProtocol.hpp index 56a0a0a1..78aad389 100644 --- a/public/common/TracyProtocol.hpp +++ b/public/common/TracyProtocol.hpp @@ -10,7 +10,7 @@ namespace tracy constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; } -constexpr uint32_t ProtocolVersion = 80; +constexpr uint32_t ProtocolVersion = 81; constexpr uint16_t BroadcastVersion = 3; using lz4sz_t = uint32_t; diff --git a/public/common/TracyQueue.hpp b/public/common/TracyQueue.hpp index dee9d94d..ec5d44d7 100644 --- a/public/common/TracyQueue.hpp +++ b/public/common/TracyQueue.hpp @@ -81,6 +81,8 @@ enum class QueueType : uint8_t SourceCodeMetadata, FiberEnter, FiberLeave, + SectionEnter, + SectionLeave, Terminate, KeepAlive, ThreadContext, @@ -309,6 +311,24 @@ struct QueueFiberLeave uint32_t thread; }; +struct QueueSectionEnter +{ + int64_t time; + uint32_t id; +}; + +struct QueueSectionEnterFat : public QueueSectionEnter +{ + uint64_t text; // ptr + uint16_t size; +}; + +struct QueueSectionLeave +{ + int64_t time; + uint32_t id; +}; + struct QueueLockTerminate { uint32_t id; @@ -921,6 +941,9 @@ struct QueueItem QueueSourceCodeNotAvailable sourceCodeNotAvailable; QueueFiberEnter fiberEnter; QueueFiberLeave fiberLeave; + QueueSectionEnter sectionEnter; + QueueSectionEnterFat sectionEnterFat; + QueueSectionLeave sectionLeave; QueueGpuZoneAnnotation zoneAnnotation; }; }; @@ -1000,6 +1023,8 @@ static constexpr size_t QueueDataSize[] = { sizeof( QueueHeader ), // SourceCodeMetadata - not for wire transfer sizeof( QueueHeader ) + sizeof( QueueFiberEnter ), sizeof( QueueHeader ) + sizeof( QueueFiberLeave ), + sizeof( QueueHeader ) + sizeof( QueueSectionEnter ), + sizeof( QueueHeader ) + sizeof( QueueSectionLeave ), // above items must be first sizeof( QueueHeader ), // terminate sizeof( QueueHeader ), // keep alive diff --git a/public/tracy/Tracy.hpp b/public/tracy/Tracy.hpp index 56e090ba..855b9e44 100644 --- a/public/tracy/Tracy.hpp +++ b/public/tracy/Tracy.hpp @@ -112,6 +112,9 @@ #define TracyIsStarted false #define TracySetProgramName(x) +#define TracySectionEnter(x, ...) 0; +#define TracySectionLeave(x) + #define TracyFiberEnter(x) #define TracyFiberEnterHint(x,y) #define TracyFiberLeave @@ -249,6 +252,9 @@ #define TracyIsConnected tracy::GetProfiler().IsConnected() #define TracySetProgramName( name ) tracy::GetProfiler().SetProgramName( name ); +#define TracySectionEnter( fmt, ... ) tracy::Profiler::SectionEnter( fmt, ##__VA_ARGS__ ); +#define TracySectionLeave( id ) tracy::Profiler::SectionLeave( id ); + #ifdef TRACY_FIBERS # define TracyFiberEnter( fiber ) tracy::Profiler::EnterFiber( fiber, 0 ) # define TracyFiberEnterHint( fiber, groupHint ) tracy::Profiler::EnterFiber( fiber, groupHint ) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 69eb1e8e..ccf16eeb 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -4857,6 +4857,12 @@ bool Worker::Process( const QueueItem& ev ) case QueueType::FiberLeave: ProcessFiberLeave( ev.fiberLeave ); break; + case QueueType::SectionEnter: + ProcessSectionEnter( ev.sectionEnter ); + break; + case QueueType::SectionLeave: + ProcessSectionLeave( ev.sectionLeave ); + break; default: assert( false ); break; @@ -7370,6 +7376,15 @@ void Worker::ProcessFiberLeave( const QueueFiberLeave& ev ) td->fiber = nullptr; } +void Worker::ProcessSectionEnter( const QueueSectionEnter& ev ) +{ +} + +void Worker::ProcessSectionLeave( const QueueSectionLeave& ev ) +{ +} + + void Worker::MemAllocChanged( MemData& memdata, int64_t time ) { const auto val = (double)memdata.usage; diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 043709e4..2868ac3c 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -846,6 +846,8 @@ private: tracy_force_inline void ProcessThreadGroupHint( const QueueThreadGroupHint& ev ); tracy_force_inline void ProcessFiberEnter( const QueueFiberEnter& ev ); tracy_force_inline void ProcessFiberLeave( const QueueFiberLeave& ev ); + tracy_force_inline void ProcessSectionEnter( const QueueSectionEnter& ev ); + tracy_force_inline void ProcessSectionLeave( const QueueSectionLeave& ev ); tracy_force_inline ZoneEvent* AllocZoneEvent(); tracy_force_inline void ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev );