From d48b3187b11b3457a9d060e045285c96b9fda49b Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 12 Aug 2020 14:06:00 +0200 Subject: [PATCH] Call stack sampling using perf events. --- client/TracySysTrace.cpp | 142 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/client/TracySysTrace.cpp b/client/TracySysTrace.cpp index 8f89cc51..bec85bc4 100644 --- a/client/TracySysTrace.cpp +++ b/client/TracySysTrace.cpp @@ -589,8 +589,14 @@ void SysTraceSendExternalName( uint64_t thread ) # include # include # include +# include +# include +# include +# include # include "TracyProfiler.hpp" +# include "TracyRingBuffer.hpp" +# include "TracyThread.hpp" # ifdef __ANDROID__ # include "TracySysTracePayload.hpp" @@ -610,6 +616,131 @@ static const char BufferSizeKb[] = "buffer_size_kb"; static const char TracePipe[] = "trace_pipe"; static std::atomic traceActive { false }; +static Thread* s_threadSampling = nullptr; +static int s_numCpus = 0; +static RingBuffer* s_ring = nullptr; + +static int perf_event_open( struct perf_event_attr* hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags ) +{ + return syscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags ); +} + +static void SetupSampling( int64_t& samplingPeriod ) +{ + samplingPeriod = 1000*1000; + + s_numCpus = (int)std::thread::hardware_concurrency(); + s_ring = (RingBuffer*)tracy_malloc( sizeof( RingBuffer ) * s_numCpus ); + + perf_event_attr pe = {}; + + pe.type = PERF_TYPE_SOFTWARE; + pe.size = sizeof( perf_event_attr ); + pe.config = PERF_COUNT_SW_CPU_CLOCK; + + pe.sample_freq = 1000; + pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_CALLCHAIN; + pe.sample_max_stack = 127; + pe.exclude_callchain_kernel = 1; + + pe.disabled = 1; + pe.freq = 1; + pe.use_clockid = 1; +#ifdef CLOCK_MONOTONIC_RAW + pe.clockid = CLOCK_MONOTONIC_RAW; +#endif + + for( int i=0; i= 0 ) break; + } + if( j == cnt ) + { + tracy_free( trace ); + } + else + { + if( j > 0 ) + { + cnt -= j; + memmove( trace+1, trace+1+j, sizeof( uint64_t ) * cnt ); + } + memcpy( trace, &cnt, sizeof( uint64_t ) ); + + TracyLfqPrepare( QueueType::CallstackSample ); + MemWrite( &item->callstackSampleFat.time, t0 ); + MemWrite( &item->callstackSampleFat.thread, (uint64_t)tid ); + MemWrite( &item->callstackSampleFat.ptr, (uint64_t)trace ); + TracyLfqCommit; + } + } + } + s_ring[i].Advance( hdr.size ); + } + if( !hadData ) + { + std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); + } + } + + for( int i=0; i~Thread(); + tracy_free( s_threadSampling ); + } } static uint64_t ReadNumber( const char*& ptr )