Group sampling globals into SysTraceState

Move the sampling client's file-level globals into a single SysTraceState
struct, so that the state of a trace session is in one place.
This commit is contained in:
Lectem
2026-10-20 19:54:22 +02:00
parent 29aa268641
commit b8935a8a56
+56 -52
View File
@@ -412,13 +412,17 @@ void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const ch
namespace tracy
{
static std::atomic<bool> traceActive { false };
static int s_numCpus = 0;
static int s_numBuffers = 0;
static int s_ctxBufferIdx = 0;
static bool s_ctxSwitchCallchain = false;
struct SysTraceState
{
std::atomic<bool> traceActive { false };
int numCpus = 0;
int numBuffers = 0;
int ctxBufferIdx = 0;
bool ctxSwitchCallchain = false;
RingBuffer* ring = nullptr;
};
static RingBuffer* s_ring = nullptr;
static SysTraceState s_state;
struct PerfIterTarget
@@ -545,9 +549,9 @@ static bool OpenSampleEvent( const PerfIterTarget& tgt, const perf_event_attr& i
TracyDebug( " Failed to setup!" );
return false;
}
new( s_ring + s_numBuffers ) RingBuffer( 64 * 1024, fd, eventId );
if( !s_ring[s_numBuffers].IsValid() ) return false;
s_numBuffers++;
new( s_state.ring + s_state.numBuffers ) RingBuffer( 64 * 1024, fd, eventId );
if( !s_state.ring[s_state.numBuffers].IsValid() ) return false;
s_state.numBuffers++;
return true;
}
@@ -1009,7 +1013,7 @@ bool SysTraceStart( int64_t& samplingPeriod )
#endif
uint32_t currentPid = externalPid != 0 ? externalPid : (uint32_t)getpid();
s_numCpus = (int)std::thread::hardware_concurrency();
s_state.numCpus = (int)std::thread::hardware_concurrency();
PerfIterTarget* iter;
int numIter;
@@ -1025,20 +1029,20 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
if( numTids == 1 )
{
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * s_numCpus );
for( int i=0; i<s_numCpus; i++ ) iter[i] = { (pid_t)tids[0], i };
numIter = s_numCpus;
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * s_state.numCpus );
for( int i=0; i<s_state.numCpus; i++ ) iter[i] = { (pid_t)tids[0], i };
numIter = s_state.numCpus;
TracyDebug( "Monitor mode: per-CPU events on pid %u (launch)", currentPid );
}
else
{
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * numTids * s_numCpus );
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * numTids * s_state.numCpus );
int k = 0;
for( int i=0; i<numTids; i++ )
{
for( int c=0; c<s_numCpus; c++ ) iter[k++] = { (pid_t)tids[i], c };
for( int c=0; c<s_state.numCpus; c++ ) iter[k++] = { (pid_t)tids[i], c };
}
numIter = numTids * s_numCpus;
numIter = numTids * s_state.numCpus;
TracyDebug( "Monitor mode: per-thread per-CPU events for %i threads of pid %u (attach)", numTids, currentPid );
}
tracy_free( tids );
@@ -1046,9 +1050,9 @@ bool SysTraceStart( int64_t& samplingPeriod )
else
#endif
{
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * s_numCpus );
for( int i=0; i<s_numCpus; i++ ) iter[i] = { (pid_t)currentPid, i };
numIter = s_numCpus;
iter = (PerfIterTarget*)tracy_malloc( sizeof( PerfIterTarget ) * s_state.numCpus );
for( int i=0; i<s_state.numCpus; i++ ) iter[i] = { (pid_t)currentPid, i };
numIter = s_state.numCpus;
}
const auto maxNumBuffers = numIter * (
@@ -1056,12 +1060,12 @@ bool SysTraceStart( int64_t& samplingPeriod )
2 + // CPU cycles + instructions retired
2 + // cache reference + miss
2 // branch retired + miss
) + s_numCpus * (
) + s_state.numCpus * (
2 + // context switches + waking ups
1 // vsync
);
s_ring = (RingBuffer*)tracy_malloc( sizeof( RingBuffer ) * maxNumBuffers );
s_numBuffers = 0;
s_state.ring = (RingBuffer*)tracy_malloc( sizeof( RingBuffer ) * maxNumBuffers );
s_state.numBuffers = 0;
// software sampling
perf_event_attr pe = {};
@@ -1165,7 +1169,7 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
}
s_ctxBufferIdx = s_numBuffers;
s_state.ctxBufferIdx = s_state.numBuffers;
// vsync
if( !noVsync && vsyncId != -1 && vsyncLayout )
@@ -1184,15 +1188,15 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
TracyDebug( "Setup vsync capture" );
for( int i=0; i<s_numCpus; i++ )
for( int i=0; i<s_state.numCpus; i++ )
{
const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );
if( fd != -1 )
{
new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventVsync, i );
if( s_ring[s_numBuffers].IsValid() )
new( s_state.ring+s_state.numBuffers ) RingBuffer( 64*1024, fd, EventVsync, i );
if( s_state.ring[s_state.numBuffers].IsValid() )
{
s_numBuffers++;
s_state.numBuffers++;
TracyDebug( " Core %i ok (EventVsync)", i );
}
}
@@ -1202,14 +1206,14 @@ bool SysTraceStart( int64_t& samplingPeriod )
// context switches
if( !noCtxSwitch && switchId != -1 && switchLayout )
{
s_ctxSwitchCallchain = !noWaitStacks;
s_state.ctxSwitchCallchain = !noWaitStacks;
pe = {};
pe.type = PERF_TYPE_TRACEPOINT;
pe.size = sizeof( perf_event_attr );
pe.sample_period = 1;
pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW;
if( s_ctxSwitchCallchain )
if( s_state.ctxSwitchCallchain )
{
pe.sample_type |= PERF_SAMPLE_CALLCHAIN;
#if LINUX_VERSION_CODE >= KERNEL_VERSION( 4, 8, 0 )
@@ -1226,15 +1230,15 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
TracyDebug( "Setup context switch capture" );
for( int i=0; i<s_numCpus; i++ )
for( int i=0; i<s_state.numCpus; i++ )
{
const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );
if( fd != -1 )
{
new( s_ring+s_numBuffers ) RingBuffer( 256*1024, fd, EventContextSwitch, i );
if( s_ring[s_numBuffers].IsValid() )
new( s_state.ring+s_state.numBuffers ) RingBuffer( 256*1024, fd, EventContextSwitch, i );
if( s_state.ring[s_state.numBuffers].IsValid() )
{
s_numBuffers++;
s_state.numBuffers++;
TracyDebug( " Core %i ok (EventContextSwitch)", i );
}
}
@@ -1260,15 +1264,15 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
TracyDebug( "Setup waking up capture" );
for( int i=0; i<s_numCpus; i++ )
for( int i=0; i<s_state.numCpus; i++ )
{
const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );
if( fd != -1 )
{
new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventWaking, i );
if( s_ring[s_numBuffers].IsValid() )
new( s_state.ring+s_state.numBuffers ) RingBuffer( 64*1024, fd, EventWaking, i );
if( s_state.ring[s_state.numBuffers].IsValid() )
{
s_numBuffers++;
s_state.numBuffers++;
TracyDebug( " Core %i ok (EventWaking)", i );
}
}
@@ -1276,25 +1280,25 @@ bool SysTraceStart( int64_t& samplingPeriod )
}
}
TracyDebug( "Ringbuffers in use: %i", s_numBuffers );
TracyDebug( "Ringbuffers in use: %i", s_state.numBuffers );
tracy_free( iter );
if( s_numBuffers == 0 || ( externalPid != 0 && s_ctxBufferIdx == 0 ) )
if( s_state.numBuffers == 0 || ( externalPid != 0 && s_state.ctxBufferIdx == 0 ) )
{
tracy_free( s_ring );
s_ring = nullptr;
tracy_free( s_state.ring );
s_state.ring = nullptr;
TracyDebug( "Failed to setup any system tracing events, system tracing disabled." );
return false;
}
traceActive.store( true, std::memory_order_relaxed );
s_state.traceActive.store( true, std::memory_order_relaxed );
return true;
}
void SysTraceStop()
{
traceActive.store( false, std::memory_order_relaxed );
s_state.traceActive.store( false, std::memory_order_relaxed );
}
static uint64_t* GetCallstackBlock( uint64_t cnt, RingBuffer& ring, uint64_t offset )
@@ -1341,16 +1345,16 @@ void SysTraceWorker( void* ptr )
InitAllocator();
sched_param sp = { 99 };
if( pthread_setschedparam( pthread_self(), SCHED_FIFO, &sp ) != 0 ) TracyDebug( "Failed to increase SysTraceWorker thread priority!" );
auto ctxBufferIdx = s_ctxBufferIdx;
auto ringArray = s_ring;
auto numBuffers = s_numBuffers;
auto ctxBufferIdx = s_state.ctxBufferIdx;
auto ringArray = s_state.ring;
auto numBuffers = s_state.numBuffers;
for( int i=0; i<numBuffers; i++ ) ringArray[i].Enable();
for(;;)
{
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() )
{
if( !traceActive.load( std::memory_order_relaxed ) ) break;
if( !s_state.traceActive.load( std::memory_order_relaxed ) ) break;
for( int i=0; i<numBuffers; i++ )
{
auto& ring = ringArray[i];
@@ -1362,7 +1366,7 @@ void SysTraceWorker( void* ptr )
ring.Advance( end );
}
}
if( !traceActive.load( std::memory_order_relaxed ) ) break;
if( !s_state.traceActive.load( std::memory_order_relaxed ) ) break;
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
continue;
}
@@ -1371,7 +1375,7 @@ void SysTraceWorker( void* ptr )
bool hadData = false;
for( int i=0; i<ctxBufferIdx; i++ )
{
if( !traceActive.load( std::memory_order_relaxed ) ) break;
if( !s_state.traceActive.load( std::memory_order_relaxed ) ) break;
auto& ring = ringArray[i];
const auto head = ring.LoadHead();
const auto tail = ring.GetTail();
@@ -1493,7 +1497,7 @@ void SysTraceWorker( void* ptr )
TRACY_ASSERT( pos == end );
ring.Advance( end );
}
if( !traceActive.load( std::memory_order_relaxed ) ) break;
if( !s_state.traceActive.load( std::memory_order_relaxed ) ) break;
if( ctxBufferIdx != numBuffers )
{
@@ -1591,7 +1595,7 @@ void SysTraceWorker( void* ptr )
uint64_t cnt = 0;
uint64_t traceOffset = 0;
if( s_ctxSwitchCallchain )
if( s_state.ctxSwitchCallchain )
{
ring.Read( &cnt, offset, sizeof( uint64_t ) );
offset += sizeof( uint64_t );
@@ -1718,7 +1722,7 @@ void SysTraceWorker( void* ptr )
}
}
}
if( !traceActive.load( std::memory_order_relaxed ) ) break;
if( !s_state.traceActive.load( std::memory_order_relaxed ) ) break;
if( !hadData )
{
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );