Implement combining sample callstacks.

This is required, because Windows will send two callstacks with the same
timestamp, one for kernel-space, second for user-space.
This commit is contained in:
Bartosz Taudul 2021-06-15 02:25:12 +02:00
parent db1dc311b0
commit 5b642cad01
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
2 changed files with 59 additions and 2 deletions

View File

@ -602,6 +602,7 @@ struct ThreadData
uint64_t ghostIdx; uint64_t ghostIdx;
#endif #endif
Vector<SampleData> samples; Vector<SampleData> samples;
SampleData pendingSample;
}; };
struct GpuCtxThreadData struct GpuCtxThreadData

View File

@ -3501,6 +3501,7 @@ ThreadData* Worker::NewThread( uint64_t thread )
#ifndef TRACY_NO_STATISTICS #ifndef TRACY_NO_STATISTICS
td->ghostIdx = 0; td->ghostIdx = 0;
#endif #endif
td->pendingSample.time.Clear();
m_data.threads.push_back( td ); m_data.threads.push_back( td );
m_threadMap.emplace( thread, td ); m_threadMap.emplace( thread, td );
m_data.threadDataLast.first = thread; m_data.threadDataLast.first = thread;
@ -5980,12 +5981,67 @@ void Worker::ProcessCallstackSample( const QueueCallstackSample& ev )
m_refTimeCtx = refTime; m_refTimeCtx = refTime;
const auto t = TscTime( refTime - m_data.baseTime ); const auto t = TscTime( refTime - m_data.baseTime );
auto& td = *NoticeThread( ev.thread );
SampleData sd; SampleData sd;
sd.time.SetVal( t ); sd.time.SetVal( t );
sd.callstack.SetVal( callstack ); sd.callstack.SetVal( callstack );
auto td = NoticeThread( ev.thread ); if( m_combineSamples )
ProcessCallstackSampleImpl( sd, *td, t, callstack ); {
const auto pendingTime = td.pendingSample.time.Val();
if( pendingTime == 0 )
{
td.pendingSample = sd;
}
else
{
if( pendingTime == t )
{
const auto& cs1 = GetCallstack( td.pendingSample.callstack.Val() );
const auto& cs2 = GetCallstack( callstack );
const auto sz1 = cs1.size();
const auto sz2 = cs2.size();
const auto tsz = sz1 + sz2;
size_t memsize = sizeof( VarArray<CallstackFrameId> ) + tsz * sizeof( CallstackFrameId );
auto mem = (char*)m_slab.AllocRaw( memsize );
memcpy( mem, cs1.data(), sizeof( CallstackFrameId ) * sz1 );
memcpy( mem + sizeof( CallstackFrameId ) * sz1, cs2.data(), sizeof( CallstackFrameId ) * sz2 );
VarArray<CallstackFrameId>* arr = (VarArray<CallstackFrameId>*)( mem + tsz * sizeof( CallstackFrameId ) );
new(arr) VarArray<CallstackFrameId>( tsz, (CallstackFrameId*)mem );
uint32_t idx;
auto it = m_data.callstackMap.find( arr );
if( it == m_data.callstackMap.end() )
{
idx = m_data.callstackPayload.size();
m_data.callstackMap.emplace( arr, idx );
m_data.callstackPayload.push_back( arr );
}
else
{
idx = it->second;
m_slab.Unalloc( memsize );
}
sd.callstack.SetVal( idx );
ProcessCallstackSampleImpl( sd, td, pendingTime, idx );
td.pendingSample.time.Clear();
}
else
{
ProcessCallstackSampleImpl( td.pendingSample, td, pendingTime, td.pendingSample.callstack.Val() );
td.pendingSample = sd;
}
}
}
else
{
ProcessCallstackSampleImpl( sd, td, t, callstack );
}
} }
void Worker::ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev ) void Worker::ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev )