mirror of
https://github.com/wolfpld/tracy
synced 2025-04-29 20:33:52 +00:00
Construct parent call stacks for sampled stack traces.
This commit is contained in:
parent
935eb4cc61
commit
6cc4de8d28
@ -354,8 +354,9 @@ union CallstackFrameId
|
|||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t idx : 63;
|
uint64_t idx : 62;
|
||||||
uint64_t sel : 1;
|
uint64_t sel : 1;
|
||||||
|
uint64_t custom : 1;
|
||||||
};
|
};
|
||||||
uint64_t data;
|
uint64_t data;
|
||||||
};
|
};
|
||||||
|
@ -30,10 +30,11 @@ namespace tracy
|
|||||||
|
|
||||||
static inline CallstackFrameId PackPointer( uint64_t ptr )
|
static inline CallstackFrameId PackPointer( uint64_t ptr )
|
||||||
{
|
{
|
||||||
assert( ( ( ptr & 0x4000000000000000 ) << 1 ) == ( ptr & 0x8000000000000000 ) );
|
assert( ( ( ptr & 0x3000000000000000 ) << 2 ) == ( ptr & 0xC000000000000000 ) );
|
||||||
CallstackFrameId id;
|
CallstackFrameId id;
|
||||||
id.idx = ptr;
|
id.idx = ptr;
|
||||||
id.sel = 0;
|
id.sel = 0;
|
||||||
|
id.custom = 0;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3123,7 +3124,7 @@ void Worker::AddFrameImageData( uint64_t ptr, const char* data, size_t sz )
|
|||||||
uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const
|
uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const
|
||||||
{
|
{
|
||||||
assert( id.sel == 0 );
|
assert( id.sel == 0 );
|
||||||
return ( id.idx & 0x7FFFFFFFFFFFFFFF ) | ( ( id.idx & 0x4000000000000000 ) << 1 );
|
return ( id.idx & 0x3FFFFFFFFFFFFFFF ) | ( ( id.idx & 0xC000000000000000 ) << 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::AddCallstackPayload( uint64_t ptr, const char* _data, size_t _sz )
|
void Worker::AddCallstackPayload( uint64_t ptr, const char* _data, size_t _sz )
|
||||||
@ -3201,6 +3202,7 @@ void Worker::AddCallstackAllocPayload( uint64_t ptr, const char* data, size_t _s
|
|||||||
frameData->size = 1;
|
frameData->size = 1;
|
||||||
id.idx = m_callstackAllocNextIdx++;
|
id.idx = m_callstackAllocNextIdx++;
|
||||||
id.sel = 1;
|
id.sel = 1;
|
||||||
|
id.custom = 0;
|
||||||
m_data.callstackFrameMap.emplace( id, frameData );
|
m_data.callstackFrameMap.emplace( id, frameData );
|
||||||
m_data.revFrameMap.emplace( frameData, id );
|
m_data.revFrameMap.emplace( frameData, id );
|
||||||
}
|
}
|
||||||
@ -5304,7 +5306,7 @@ void Worker::UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool ca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSampleStatisticsImpl( frames, cssz, count );
|
UpdateSampleStatisticsImpl( frames, cssz, count, cs );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it )
|
void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it )
|
||||||
@ -5324,20 +5326,20 @@ void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postpo
|
|||||||
frames[i] = frame;
|
frames[i] = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSampleStatisticsImpl( frames, cssz, it->second );
|
UpdateSampleStatisticsImpl( frames, cssz, it->second, cs );
|
||||||
it = m_data.postponedSamples.erase( it );
|
it = m_data.postponedSamples.erase( it );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count )
|
void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count, const VarArray<CallstackFrameId>& cs )
|
||||||
{
|
{
|
||||||
{
|
|
||||||
const auto fexcl = frames[0];
|
const auto fexcl = frames[0];
|
||||||
const auto fsz = fexcl->size;
|
const auto fxsz = fexcl->size;
|
||||||
|
{
|
||||||
const auto& frame0 = fexcl->data[0];
|
const auto& frame0 = fexcl->data[0];
|
||||||
auto sym = m_data.symbolStats.find( frame0.symAddr );
|
auto sym = m_data.symbolStats.find( frame0.symAddr );
|
||||||
if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame0.symAddr, SymbolStats {} ).first;
|
if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame0.symAddr, SymbolStats {} ).first;
|
||||||
sym->second.excl += count;
|
sym->second.excl += count;
|
||||||
for( uint8_t f=1; f<fsz; f++ )
|
for( uint8_t f=1; f<fxsz; f++ )
|
||||||
{
|
{
|
||||||
const auto& frame = fexcl->data[f];
|
const auto& frame = fexcl->data[f];
|
||||||
sym = m_data.symbolStats.find( frame.symAddr );
|
sym = m_data.symbolStats.find( frame.symAddr );
|
||||||
@ -5357,6 +5359,78 @@ void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint
|
|||||||
sym->second.incl += count;
|
sym->second.incl += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallstackFrameId parentFrameId;
|
||||||
|
if( fxsz != 1 )
|
||||||
|
{
|
||||||
|
auto cfdata = (CallstackFrame*)alloca( ( fxsz-1 ) * sizeof( CallstackFrame ) );
|
||||||
|
for( int i=0; i<fxsz-1; i++ )
|
||||||
|
{
|
||||||
|
cfdata[i] = fexcl->data[i+1];
|
||||||
|
}
|
||||||
|
CallstackFrameData cfd;
|
||||||
|
cfd.data = cfdata;
|
||||||
|
cfd.size = fxsz-1;
|
||||||
|
cfd.imageName = fexcl->imageName;
|
||||||
|
|
||||||
|
auto it = m_data.revParentFrameMap.find( &cfd );
|
||||||
|
if( it == m_data.revParentFrameMap.end() )
|
||||||
|
{
|
||||||
|
auto frame = m_slab.Alloc<CallstackFrame>( fxsz-1 );
|
||||||
|
memcpy( frame, cfdata, fxsz * sizeof( CallstackFrame ) );
|
||||||
|
auto frameData = m_slab.AllocInit<CallstackFrameData>();
|
||||||
|
frameData->data = frame;
|
||||||
|
frameData->size = fxsz - 1;
|
||||||
|
parentFrameId.idx = m_callstackParentNextIdx++;
|
||||||
|
parentFrameId.sel = 0;
|
||||||
|
parentFrameId.custom = 1;
|
||||||
|
m_data.callstackFrameMap.emplace( parentFrameId, frameData );
|
||||||
|
m_data.revParentFrameMap.emplace( frameData, parentFrameId );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentFrameId = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto sz = framesCount - ( fxsz == 1 );
|
||||||
|
const auto memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );
|
||||||
|
auto mem = (char*)m_slab.AllocRaw( memsize );
|
||||||
|
|
||||||
|
auto data = (CallstackFrameId*)mem;
|
||||||
|
auto dst = data;
|
||||||
|
if( fxsz == 1 )
|
||||||
|
{
|
||||||
|
for( int i=0; i<sz; i++ )
|
||||||
|
{
|
||||||
|
*dst++ = cs[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dst++ = parentFrameId;
|
||||||
|
for( int i=1; i<sz; i++ )
|
||||||
|
{
|
||||||
|
*dst++ = cs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );
|
||||||
|
new(arr) VarArray<CallstackFrameId>( sz, data );
|
||||||
|
|
||||||
|
uint32_t idx;
|
||||||
|
auto it = m_data.parentCallstackMap.find( arr );
|
||||||
|
if( it == m_data.parentCallstackMap.end() )
|
||||||
|
{
|
||||||
|
idx = m_data.parentCallstackPayload.size();
|
||||||
|
m_data.parentCallstackMap.emplace( arr, idx );
|
||||||
|
m_data.parentCallstackPayload.push_back( arr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
idx = it->second;
|
||||||
|
m_slab.Unalloc( memsize );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -227,6 +227,9 @@ private:
|
|||||||
unordered_flat_map<uint64_t, SymbolStats> symbolStats;
|
unordered_flat_map<uint64_t, SymbolStats> symbolStats;
|
||||||
|
|
||||||
#ifndef TRACY_NO_STATISTICS
|
#ifndef TRACY_NO_STATISTICS
|
||||||
|
unordered_flat_map<VarArray<CallstackFrameId>*, uint32_t, VarArrayHasher<CallstackFrameId>, VarArrayComparator<CallstackFrameId>> parentCallstackMap;
|
||||||
|
Vector<short_ptr<VarArray<CallstackFrameId>>> parentCallstackPayload;
|
||||||
|
unordered_flat_map<CallstackFrameData*, CallstackFrameId, RevFrameHash, RevFrameComp> revParentFrameMap;
|
||||||
unordered_flat_map<uint32_t, uint32_t> postponedSamples;
|
unordered_flat_map<uint32_t, uint32_t> postponedSamples;
|
||||||
bool newFramesWereReceived = false;
|
bool newFramesWereReceived = false;
|
||||||
bool callstackSamplesReady = false;
|
bool callstackSamplesReady = false;
|
||||||
@ -643,7 +646,7 @@ private:
|
|||||||
void ReconstructContextSwitchUsage();
|
void ReconstructContextSwitchUsage();
|
||||||
void UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool canPostpone );
|
void UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool canPostpone );
|
||||||
void UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it );
|
void UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it );
|
||||||
void UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count );
|
void UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint8_t framesCount, uint32_t count, const VarArray<CallstackFrameId>& cs );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tracy_force_inline int64_t ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx );
|
tracy_force_inline int64_t ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx );
|
||||||
@ -731,6 +734,7 @@ private:
|
|||||||
CallstackFrameData* m_callstackFrameStaging;
|
CallstackFrameData* m_callstackFrameStaging;
|
||||||
uint64_t m_callstackFrameStagingPtr;
|
uint64_t m_callstackFrameStagingPtr;
|
||||||
uint64_t m_callstackAllocNextIdx = 0;
|
uint64_t m_callstackAllocNextIdx = 0;
|
||||||
|
uint64_t m_callstackParentNextIdx = 0;
|
||||||
|
|
||||||
uint64_t m_lastMemActionCallstack;
|
uint64_t m_lastMemActionCallstack;
|
||||||
bool m_lastMemActionWasAlloc;
|
bool m_lastMemActionWasAlloc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user