mirror of
https://github.com/wolfpld/tracy.git
synced 2026-11-14 03:45:27 +00:00
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:
@@ -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 ) );
|
||||
|
||||
Reference in New Issue
Block a user