mirror of
https://github.com/wolfpld/tracy.git
synced 2025-03-20 07:40:02 +08:00
Make it possible to store multiple frames at single frame address.
This commit is contained in:
@@ -171,6 +171,15 @@ struct CallstackFrame
|
||||
|
||||
enum { CallstackFrameSize = sizeof( CallstackFrame ) };
|
||||
|
||||
struct CallstackFrameData
|
||||
{
|
||||
CallstackFrame* data;
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
enum { CallstackFrameDataSize = sizeof( CallstackFrameData ) };
|
||||
|
||||
|
||||
struct CallstackFrameTree
|
||||
{
|
||||
uint64_t frame;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Version
|
||||
{
|
||||
enum { Major = 0 };
|
||||
enum { Minor = 4 };
|
||||
enum { Patch = 2 };
|
||||
enum { Patch = 3 };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+69
-53
@@ -3616,7 +3616,8 @@ void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, B
|
||||
}
|
||||
for( int8_t j=1; j<idx; j++ )
|
||||
{
|
||||
auto frame = worker.GetCallstackFrame( prevCs[j] );
|
||||
auto frameData = worker.GetCallstackFrame( prevCs[j] );
|
||||
auto frame = frameData->data;
|
||||
ImGui::TextDisabled( "%s", worker.GetString( frame->name ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
@@ -3672,7 +3673,8 @@ void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, B
|
||||
const auto csz = cs.size();
|
||||
for( uint8_t i=1; i<csz; i++ )
|
||||
{
|
||||
auto frame = worker.GetCallstackFrame( cs[i] );
|
||||
auto frameData = worker.GetCallstackFrame( cs[i] );
|
||||
auto frame = frameData->data;
|
||||
ImGui::TextDisabled( "%s", worker.GetString( frame->name ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
@@ -5559,7 +5561,7 @@ void View::DrawFindZone()
|
||||
else
|
||||
{
|
||||
auto& callstack = m_worker.GetCallstack( v->first );
|
||||
hdrString = m_worker.GetString( m_worker.GetCallstackFrame( *callstack.begin() )->name );
|
||||
hdrString = m_worker.GetString( m_worker.GetCallstackFrame( *callstack.begin() )->data[0].name );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -6463,14 +6465,11 @@ void View::DrawCallstackWindow()
|
||||
ImGui::NextColumn();
|
||||
|
||||
int fidx = 0;
|
||||
int bidx = 0;
|
||||
for( auto& entry : cs )
|
||||
{
|
||||
ImGui::Separator();
|
||||
ImGui::Text( "%i", fidx++ );
|
||||
ImGui::NextColumn();
|
||||
|
||||
auto frame = m_worker.GetCallstackFrame( entry );
|
||||
if( !frame )
|
||||
auto frameData = m_worker.GetCallstackFrame( entry );
|
||||
if( !frameData )
|
||||
{
|
||||
char buf[32];
|
||||
sprintf( buf, "%p", (void*)entry );
|
||||
@@ -6484,64 +6483,81 @@ void View::DrawCallstackWindow()
|
||||
}
|
||||
else
|
||||
{
|
||||
auto txt = m_worker.GetString( frame->name );
|
||||
ImGui::TextWrapped( "%s", txt );
|
||||
if( ImGui::IsItemClicked() )
|
||||
for( uint8_t f=0; f<frameData->size; f++ )
|
||||
{
|
||||
ImGui::SetClipboardText( txt );
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushTextWrapPos( 0.0f );
|
||||
float indentVal = 0.f;
|
||||
if( m_callstackBuzzAnim.Match( fidx ) )
|
||||
{
|
||||
const auto time = m_callstackBuzzAnim.Time();
|
||||
indentVal = sin( time * 60.f ) * 10.f * time;
|
||||
ImGui::Indent( indentVal );
|
||||
}
|
||||
txt = m_worker.GetString( frame->file );
|
||||
if( m_showCallstackFrameAddress )
|
||||
{
|
||||
ImGui::TextDisabled( "0x%" PRIx64, entry );
|
||||
if( ImGui::IsItemClicked() )
|
||||
const auto& frame = frameData->data[f];
|
||||
bidx++;
|
||||
|
||||
ImGui::Separator();
|
||||
if( f == 0 )
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf( tmp, "0x%" PRIx64, entry );
|
||||
ImGui::SetClipboardText( tmp );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( frame->line == 0 )
|
||||
{
|
||||
ImGui::TextDisabled( "%s", txt );
|
||||
ImGui::Text( "%i", fidx++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TextDisabled( "%s:%i", txt, frame->line );
|
||||
ImGui::TextDisabled( "inline" );
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
|
||||
auto txt = m_worker.GetString( frame.name );
|
||||
ImGui::TextWrapped( "%s", txt );
|
||||
if( ImGui::IsItemClicked() )
|
||||
{
|
||||
ImGui::SetClipboardText( txt );
|
||||
}
|
||||
}
|
||||
if( ImGui::IsItemClicked( 1 ) )
|
||||
{
|
||||
if( FileExists( txt ) )
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushTextWrapPos( 0.0f );
|
||||
float indentVal = 0.f;
|
||||
if( m_callstackBuzzAnim.Match( bidx ) )
|
||||
{
|
||||
SetTextEditorFile( txt, frame->line );
|
||||
const auto time = m_callstackBuzzAnim.Time();
|
||||
indentVal = sin( time * 60.f ) * 10.f * time;
|
||||
ImGui::Indent( indentVal );
|
||||
}
|
||||
txt = m_worker.GetString( frame.file );
|
||||
if( m_showCallstackFrameAddress )
|
||||
{
|
||||
ImGui::TextDisabled( "0x%" PRIx64, entry );
|
||||
if( ImGui::IsItemClicked() )
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf( tmp, "0x%" PRIx64, entry );
|
||||
ImGui::SetClipboardText( tmp );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_callstackBuzzAnim.Enable( fidx, 0.5f );
|
||||
if( frame.line == 0 )
|
||||
{
|
||||
ImGui::TextDisabled( "%s", txt );
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TextDisabled( "%s:%i", txt, frame.line );
|
||||
}
|
||||
if( ImGui::IsItemClicked() )
|
||||
{
|
||||
ImGui::SetClipboardText( txt );
|
||||
}
|
||||
}
|
||||
if( ImGui::IsItemClicked( 1 ) )
|
||||
{
|
||||
if( FileExists( txt ) )
|
||||
{
|
||||
SetTextEditorFile( txt, frame.line );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_callstackBuzzAnim.Enable( bidx, 0.5f );
|
||||
}
|
||||
}
|
||||
if( indentVal != 0.f )
|
||||
{
|
||||
ImGui::Unindent( indentVal );
|
||||
}
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
if( indentVal != 0.f )
|
||||
{
|
||||
ImGui::Unindent( indentVal );
|
||||
}
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7910,7 +7926,7 @@ void View::DrawFrameTreeLevel( std::vector<CallstackFrameTree>& tree, int& idx )
|
||||
for( auto& v : tree )
|
||||
{
|
||||
idx++;
|
||||
auto frame = m_worker.GetCallstackFrame( v.frame );
|
||||
auto frame = m_worker.GetCallstackFrame( v.frame )->data;
|
||||
bool expand = false;
|
||||
if( v.children.empty() )
|
||||
{
|
||||
@@ -8454,7 +8470,7 @@ void View::CallstackTooltip( uint32_t idx )
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text( "%s", m_worker.GetString( frame->name ) );
|
||||
ImGui::Text( "%s", m_worker.GetString( frame->data->name ) );
|
||||
}
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
|
||||
+76
-20
@@ -14,6 +14,7 @@
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#if ( defined _MSC_VER && _MSVC_LANG >= 201703L ) || __cplusplus >= 201703L
|
||||
# if __has_include(<execution>)
|
||||
@@ -217,6 +218,8 @@ Worker::Worker( const char* addr )
|
||||
, m_pendingThreads( 0 )
|
||||
, m_pendingSourceLocation( 0 )
|
||||
, m_pendingCallstackFrames( 0 )
|
||||
, m_pendingCallstackSubframes( 0 )
|
||||
, m_callstackFrameStaging( nullptr )
|
||||
, m_traceVersion( CurrentVersion )
|
||||
, m_loadTime( 0 )
|
||||
{
|
||||
@@ -1020,17 +1023,41 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
|
||||
m_data.callstackPayload.push_back_no_space_check( arr );
|
||||
}
|
||||
|
||||
f.Read( sz );
|
||||
m_data.callstackFrameMap.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
if( fileVer >= FileVersion( 0, 4, 3 ) )
|
||||
{
|
||||
uint64_t ptr;
|
||||
f.Read( ptr );
|
||||
f.Read( sz );
|
||||
m_data.callstackFrameMap.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
uint64_t ptr;
|
||||
f.Read( ptr );
|
||||
|
||||
auto frame = m_slab.Alloc<CallstackFrame>();
|
||||
f.Read( frame, sizeof( CallstackFrame ) );
|
||||
auto frameData = m_slab.Alloc<CallstackFrameData>();
|
||||
f.Read( frameData->size );
|
||||
|
||||
m_data.callstackFrameMap.emplace( ptr, frame );
|
||||
frameData->data = m_slab.Alloc<CallstackFrame>( frameData->size );
|
||||
f.Read( frameData->data, sizeof( CallstackFrame ) * frameData->size );
|
||||
|
||||
m_data.callstackFrameMap.emplace( ptr, frameData );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
f.Read( sz );
|
||||
m_data.callstackFrameMap.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
uint64_t ptr;
|
||||
f.Read( ptr );
|
||||
|
||||
auto frameData = m_slab.Alloc<CallstackFrameData>();
|
||||
frameData->size = 1;
|
||||
|
||||
frameData->data = m_slab.Alloc<CallstackFrame>();
|
||||
f.Read( frameData->data, sizeof( CallstackFrame ) );
|
||||
|
||||
m_data.callstackFrameMap.emplace( ptr, frameData );
|
||||
}
|
||||
}
|
||||
|
||||
finishLoading:
|
||||
@@ -1201,7 +1228,7 @@ std::pair <int, int> Worker::GetFrameRange( const FrameData& fd, int64_t from, i
|
||||
return std::make_pair( zbegin, zend );
|
||||
}
|
||||
|
||||
const CallstackFrame* Worker::GetCallstackFrame( uint64_t ptr ) const
|
||||
const CallstackFrameData* Worker::GetCallstackFrame( uint64_t ptr ) const
|
||||
{
|
||||
auto it = m_data.callstackFrameMap.find( ptr );
|
||||
if( it == m_data.callstackFrameMap.end() )
|
||||
@@ -1582,7 +1609,7 @@ void Worker::Exec()
|
||||
if( m_terminate )
|
||||
{
|
||||
if( m_pendingStrings != 0 || m_pendingThreads != 0 || m_pendingSourceLocation != 0 || m_pendingCallstackFrames != 0 ||
|
||||
!m_pendingCustomStrings.empty() || m_data.plots.IsPending() || !m_pendingCallstacks.empty() )
|
||||
!m_pendingCustomStrings.empty() || m_data.plots.IsPending() || !m_pendingCallstacks.empty() || m_pendingCallstackSubframes != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -2197,6 +2224,9 @@ bool Worker::Process( const QueueItem& ev )
|
||||
case QueueType::Callstack:
|
||||
ProcessCallstack( ev.callstack );
|
||||
break;
|
||||
case QueueType::CallstackFrameSize:
|
||||
ProcessCallstackFrameSize( ev.callstackFrameSize );
|
||||
break;
|
||||
case QueueType::CallstackFrame:
|
||||
ProcessCallstackFrame( ev.callstackFrame );
|
||||
break;
|
||||
@@ -2961,28 +2991,53 @@ void Worker::ProcessCallstack( const QueueCallstack& ev )
|
||||
m_pendingCallstacks.erase( it );
|
||||
}
|
||||
|
||||
void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev )
|
||||
void Worker::ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev )
|
||||
{
|
||||
assert( !m_callstackFrameStaging );
|
||||
assert( m_pendingCallstackSubframes == 0 );
|
||||
assert( m_pendingCallstackFrames > 0 );
|
||||
m_pendingCallstackFrames--;
|
||||
m_pendingCallstackSubframes = ev.size;
|
||||
|
||||
// Frames may be duplicated due to recursion
|
||||
auto fmit = m_data.callstackFrameMap.find( ev.ptr );
|
||||
if( fmit == m_data.callstackFrameMap.end() )
|
||||
{
|
||||
m_callstackFrameStaging = m_slab.Alloc<CallstackFrameData>();
|
||||
m_callstackFrameStaging->size = ev.size;
|
||||
m_callstackFrameStaging->data = m_slab.Alloc<CallstackFrame>( ev.size );
|
||||
|
||||
m_callstackFrameStagingPtr = ev.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev )
|
||||
{
|
||||
assert( m_pendingCallstackSubframes > 0 );
|
||||
|
||||
auto nit = m_pendingCustomStrings.find( ev.name );
|
||||
assert( nit != m_pendingCustomStrings.end() );
|
||||
auto fit = m_pendingCustomStrings.find( ev.file );
|
||||
assert( fit != m_pendingCustomStrings.end() );
|
||||
|
||||
// Frames may be duplicated due to recursion
|
||||
if( fmit == m_data.callstackFrameMap.end() )
|
||||
if( m_callstackFrameStaging )
|
||||
{
|
||||
CheckString( ev.file );
|
||||
const auto idx = m_callstackFrameStaging->size - m_pendingCallstackSubframes;
|
||||
|
||||
auto frame = m_slab.Alloc<CallstackFrame>();
|
||||
frame->name = StringIdx( nit->second.idx );
|
||||
frame->file = StringIdx( fit->second.idx );
|
||||
frame->line = ev.line;
|
||||
m_callstackFrameStaging->data[idx].name = StringIdx( nit->second.idx );
|
||||
m_callstackFrameStaging->data[idx].file = StringIdx( fit->second.idx );
|
||||
m_callstackFrameStaging->data[idx].line = ev.line;
|
||||
|
||||
m_data.callstackFrameMap.emplace( ev.ptr, frame );
|
||||
if( --m_pendingCallstackSubframes == 0 )
|
||||
{
|
||||
assert( m_data.callstackFrameMap.find( m_callstackFrameStagingPtr ) == m_data.callstackFrameMap.end() );
|
||||
m_data.callstackFrameMap.emplace( m_callstackFrameStagingPtr, m_callstackFrameStaging );
|
||||
m_callstackFrameStaging = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pendingCallstackSubframes--;
|
||||
}
|
||||
|
||||
m_pendingCustomStrings.erase( nit );
|
||||
@@ -3622,7 +3677,8 @@ void Worker::Write( FileWrite& f )
|
||||
for( auto& frame : m_data.callstackFrameMap )
|
||||
{
|
||||
f.Write( &frame.first, sizeof( uint64_t ) );
|
||||
f.Write( frame.second, sizeof( CallstackFrame ) );
|
||||
f.Write( &frame.second->size, sizeof( frame.second->size ) );
|
||||
f.Write( frame.second->data, sizeof( CallstackFrame ) * frame.second->size );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ private:
|
||||
|
||||
flat_hash_map<VarArray<uint64_t>*, uint32_t, VarArrayHasherPOT<uint64_t>, VarArrayComparator<uint64_t>> callstackMap;
|
||||
Vector<VarArray<uint64_t>*> callstackPayload;
|
||||
flat_hash_map<uint64_t, CallstackFrame*> callstackFrameMap;
|
||||
flat_hash_map<uint64_t, CallstackFrameData*> callstackFrameMap;
|
||||
|
||||
std::map<uint32_t, LockMap> lockMap;
|
||||
|
||||
@@ -229,7 +229,7 @@ public:
|
||||
const MemData& GetMemData() const { return m_data.memory; }
|
||||
|
||||
const VarArray<uint64_t>& GetCallstack( uint32_t idx ) const { return *m_data.callstackPayload[idx]; }
|
||||
const CallstackFrame* GetCallstackFrame( uint64_t ptr ) const;
|
||||
const CallstackFrameData* GetCallstackFrame( uint64_t ptr ) const;
|
||||
|
||||
const CrashEvent& GetCrashEvent() const { return m_data.m_crashEvent; }
|
||||
|
||||
@@ -331,6 +331,7 @@ private:
|
||||
tracy_force_inline void ProcessMemFreeCallstack( const QueueMemFree& ev );
|
||||
tracy_force_inline void ProcessCallstackMemory( const QueueCallstackMemory& ev );
|
||||
tracy_force_inline void ProcessCallstack( const QueueCallstack& ev );
|
||||
tracy_force_inline void ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev );
|
||||
tracy_force_inline void ProcessCallstackFrame( const QueueCallstackFrame& ev );
|
||||
tracy_force_inline void ProcessCrashReport( const QueueCrashReport& ev );
|
||||
|
||||
@@ -438,6 +439,10 @@ private:
|
||||
uint32_t m_pendingThreads;
|
||||
uint32_t m_pendingSourceLocation;
|
||||
uint32_t m_pendingCallstackFrames;
|
||||
uint8_t m_pendingCallstackSubframes;
|
||||
|
||||
CallstackFrameData* m_callstackFrameStaging;
|
||||
uint64_t m_callstackFrameStagingPtr;
|
||||
|
||||
uint64_t m_lastMemActionCallstack;
|
||||
bool m_lastMemActionWasAlloc;
|
||||
|
||||
Reference in New Issue
Block a user