diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 1c69f422..e373611a 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -215,6 +215,12 @@ static_assert( std::is_standard_layout::value, "GpuEvent is not standa struct MemEvent { + tracy_force_inline uint64_t Ptr() const { return uint64_t( int64_t( _ptr_csalloc1 ) >> 8 ); } + tracy_force_inline void SetPtr( uint64_t ptr ) { memcpy( ((char*)&_ptr_csalloc1)+1, &ptr, 4 ); memcpy( ((char*)&_ptr_csalloc1)+5, ((char*)&ptr)+4, 2 ); memcpy( ((char*)&_ptr_csalloc1)+7, ((char*)&ptr)+6, 1 ); } + tracy_force_inline uint64_t Size() const { return _size_csalloc2 >> 16; } + tracy_force_inline void SetSize( uint64_t size ) { assert( size < ( 1ull << 47 ) ); memcpy( ((char*)&_size_csalloc2)+2, &size, 4 ); memcpy( ((char*)&_size_csalloc2)+6, ((char*)&size)+4, 2 ); } + tracy_force_inline uint32_t CsAlloc() const { return uint8_t( _ptr_csalloc1 ) | ( uint16_t( _size_csalloc2 ) << 8 ); } + tracy_force_inline void SetCsAlloc( uint32_t csAlloc ) { memcpy( &_ptr_csalloc1, &csAlloc, 1 ); memcpy( &_size_csalloc2, ((char*)&csAlloc)+1, 2 ); } tracy_force_inline int64_t TimeAlloc() const { return int64_t( _time_thread_alloc ) >> 16; } tracy_force_inline void SetTimeAlloc( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_thread_alloc)+2, &time, 4 ); memcpy( ((char*)&_time_thread_alloc)+6, ((char*)&time)+4, 2 ); } tracy_force_inline int64_t TimeFree() const { return int64_t( _time_thread_free ) >> 16; } @@ -224,9 +230,8 @@ struct MemEvent tracy_force_inline uint16_t ThreadFree() const { return uint16_t( _time_thread_free ); } tracy_force_inline void SetThreadFree( uint16_t thread ) { memcpy( &_time_thread_free, &thread, 2 ); } - uint64_t ptr; - uint64_t size; - Int24 csAlloc; + uint64_t _ptr_csalloc1; + uint64_t _size_csalloc2; Int24 csFree; uint64_t _time_thread_alloc; uint64_t _time_thread_free; diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 25eef61c..bd4b139b 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -5194,7 +5194,7 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint ImGui::Separator(); TextDisabledUnformatted( "Address:" ); ImGui::SameLine(); - ImGui::Text( "0x%" PRIx64, ev->ptr ); + ImGui::Text( "0x%" PRIx64, ev->Ptr() ); TextFocused( "Appeared at", TimeToString( ev->TimeAlloc() ) ); if( change > 0 ) { @@ -5861,7 +5861,7 @@ void View::DrawZoneInfoWindow() { if( ait->ThreadAlloc() == thread ) { - cAlloc += ait->size; + cAlloc += ait->Size(); nAlloc++; } ait++; @@ -5870,7 +5870,7 @@ void View::DrawZoneInfoWindow() { if( mem.data[*fit].ThreadFree() == thread ) { - cFree += mem.data[*fit].size; + cFree += mem.data[*fit].Size(); nFree++; } fit++; @@ -5929,7 +5929,7 @@ void View::DrawZoneInfoWindow() pdqsort_branchless( v.begin(), v.end(), [] ( const auto& l, const auto& r ) { return l->TimeAlloc() < r->TimeAlloc(); } ); ListMemData( v.begin(), v.end(), []( auto& v ) { - ImGui::Text( "0x%" PRIx64, (*v)->ptr ); + ImGui::Text( "0x%" PRIx64, (*v)->Ptr() ); }, nullptr, m_allocTimeRelativeToZone ? ev.Start() : -1 ); ImGui::TreePop(); } @@ -10343,13 +10343,13 @@ void View::DrawMemoryAllocWindow() } char buf[64]; - sprintf( buf, "0x%" PRIx64, ev.ptr ); + sprintf( buf, "0x%" PRIx64, ev.Ptr() ); TextFocused( "Address:", buf ); - TextFocused( "Size:", MemSizeToString( ev.size ) ); - if( ev.size >= 10000ll ) + TextFocused( "Size:", MemSizeToString( ev.Size() ) ); + if( ev.Size() >= 10000ll ) { ImGui::SameLine(); - ImGui::TextDisabled( "(%s bytes)", RealToString( ev.size, true ) ); + ImGui::TextDisabled( "(%s bytes)", RealToString( ev.Size(), true ) ); } ImGui::Separator(); TextFocused( "Appeared at", TimeToString( ev.TimeAlloc() ) ); @@ -10360,10 +10360,10 @@ void View::DrawMemoryAllocWindow() ImGui::TextDisabled( "(%s)", RealToString( tidAlloc, true ) ); ImGui::SameLine(); SmallColorBox( GetThreadColor( tidAlloc, 0 ) ); - if( ev.csAlloc.Val() != 0 ) + if( ev.CsAlloc() != 0 ) { ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); - SmallCallstackButton( "Call stack", ev.csAlloc.Val(), idx ); + SmallCallstackButton( "Call stack", ev.CsAlloc(), idx ); } if( ev.TimeFree() < 0 ) { @@ -11818,7 +11818,7 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress, const m_memoryAllocHoverWait = 2; } ImGui::NextColumn(); - ImGui::TextUnformatted( MemSizeToString( v->size ) ); + ImGui::TextUnformatted( MemSizeToString( v->Size() ) ); ImGui::NextColumn(); ImGui::PushID( idx++ ); if( ImGui::Selectable( TimeToString( v->TimeAlloc() - startTime ) ) ) @@ -11941,13 +11941,13 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress, const } } ImGui::NextColumn(); - if( v->csAlloc.Val() == 0 ) + if( v->CsAlloc() == 0 ) { TextDisabledUnformatted( "[alloc]" ); } else { - SmallCallstackButton( "alloc", v->csAlloc.Val(), idx ); + SmallCallstackButton( "alloc", v->CsAlloc(), idx ); } ImGui::SameLine(); ImGui::Spacing(); @@ -12002,19 +12002,19 @@ flat_hash_map> View::GetCallstackPath { for( auto& ev : mem.data ) { - if( ev.csAlloc.Val() == 0 ) continue; + if( ev.CsAlloc() == 0 ) continue; if( ev.TimeAlloc() >= zvMid ) continue; if( onlyActive && ev.TimeFree() >= 0 && ev.TimeFree() < zvMid ) continue; - auto it = pathSum.find( ev.csAlloc.Val() ); + auto it = pathSum.find( ev.CsAlloc() ); if( it == pathSum.end() ) { - pathSum.emplace( ev.csAlloc.Val(), PathData { 1, ev.size } ); + pathSum.emplace( ev.CsAlloc(), PathData { 1, ev.Size() } ); } else { it->second.cnt++; - it->second.mem += ev.size; + it->second.mem += ev.Size(); } } } @@ -12022,18 +12022,18 @@ flat_hash_map> View::GetCallstackPath { for( auto& ev : mem.data ) { - if( ev.csAlloc.Val() == 0 ) continue; + if( ev.CsAlloc() == 0 ) continue; if( onlyActive && ev.TimeFree() >= 0 ) continue; - auto it = pathSum.find( ev.csAlloc.Val() ); + auto it = pathSum.find( ev.CsAlloc() ); if( it == pathSum.end() ) { - pathSum.emplace( ev.csAlloc.Val(), PathData { 1, ev.size } ); + pathSum.emplace( ev.CsAlloc(), PathData { 1, ev.Size() } ); } else { it->second.cnt++; - it->second.mem += ev.size; + it->second.mem += ev.Size(); } } } @@ -12254,8 +12254,8 @@ std::vector View::GetMemoryPages() const { auto& alloc = *it; - const auto a0 = alloc.ptr - memlow; - const auto a1 = a0 + alloc.size; + const auto a0 = alloc.Ptr() - memlow; + const auto a1 = a0 + alloc.Size(); int8_t val = alloc.TimeFree() < 0 ? int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.TimeAlloc() ) >> 24 ) ) ) : ( alloc.TimeFree() > zvMid ? @@ -12273,8 +12273,8 @@ std::vector View::GetMemoryPages() const const auto lastTime = m_worker.GetLastTime(); for( auto& alloc : mem.data ) { - const auto a0 = alloc.ptr - memlow; - const auto a1 = a0 + alloc.size; + const auto a0 = alloc.Ptr() - memlow; + const auto a1 = a0 + alloc.Size(); const int8_t val = alloc.TimeFree() < 0 ? int8_t( std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeAlloc() ) ) >> 24 ) ) ) : int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeFree() ) ) >> 24 ) ) ); @@ -12375,7 +12375,7 @@ void View::DrawMemory() { for( auto& v : mem.data ) { - if( v.ptr <= m_memInfo.ptrFind && v.ptr + v.size > m_memInfo.ptrFind && v.TimeAlloc() < zvMid ) + if( v.Ptr() <= m_memInfo.ptrFind && v.Ptr() + v.Size() > m_memInfo.ptrFind && v.TimeAlloc() < zvMid ) { match.emplace_back( &v ); } @@ -12385,7 +12385,7 @@ void View::DrawMemory() { for( auto& v : mem.data ) { - if( v.ptr <= m_memInfo.ptrFind && v.ptr + v.size > m_memInfo.ptrFind ) + if( v.Ptr() <= m_memInfo.ptrFind && v.Ptr() + v.Size() > m_memInfo.ptrFind ) { match.emplace_back( &v ); } @@ -12400,13 +12400,13 @@ void View::DrawMemory() { ListMemData( match.begin(), match.end(), [this]( auto& it ) { auto& v = *it; - if( v->ptr == m_memInfo.ptrFind ) + if( v->Ptr() == m_memInfo.ptrFind ) { ImGui::Text( "0x%" PRIx64, m_memInfo.ptrFind ); } else { - ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->ptr, m_memInfo.ptrFind - v->ptr ); + ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->Ptr(), m_memInfo.ptrFind - v->Ptr() ); } }, "##allocations" ); } @@ -12431,7 +12431,7 @@ void View::DrawMemory() if( v.TimeAlloc() < zvMid && ( v.TimeFree() > zvMid || v.TimeFree() < 0 ) ) { items.emplace_back( &v ); - total += v.size; + total += v.Size(); } } } @@ -12456,7 +12456,7 @@ void View::DrawMemory() if( !items.empty() ) { ListMemData( items.begin(), items.end(), []( auto& v ) { - ImGui::Text( "0x%" PRIx64, (*v)->ptr ); + ImGui::Text( "0x%" PRIx64, (*v)->Ptr() ); }, "##activeMem" ); } else @@ -12649,7 +12649,7 @@ void View::DrawFrameTreeLevel( const flat_hash_map( data.begin(), data.end(), []( auto& v ) { - ImGui::Text( "0x%" PRIx64, (*v)->ptr ); + ImGui::Text( "0x%" PRIx64, (*v)->Ptr() ); }, "##allocations" ); ImGui::End(); } diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index aabbf71c..a7d7aebb 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1119,7 +1119,14 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) for( uint64_t i=0; iSetPtr( ptr ); + mem->SetSize( size ); + mem->SetCsAlloc( csAlloc.Val() ); + f.Read( &mem->csFree, sizeof( mem->csFree ) ); int64_t timeAlloc, timeFree; uint16_t threadAlloc, threadFree; f.Read2( timeAlloc, timeFree ); @@ -1134,7 +1141,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) else { mem->SetTimeFree( timeFree ); - active.emplace( mem->ptr, i ); + active.emplace( ptr, i ); } mem->SetThreadAlloc( threadAlloc ); mem->SetThreadFree( threadFree ); @@ -1149,7 +1156,13 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) for( uint64_t i=0; iSetPtr( ptr ); + mem->SetSize( size ); + mem->SetCsAlloc( csAlloc.Val() ); f.Skip( 1 ); f.Read( &mem->csFree, sizeof( MemEvent::csFree ) ); f.Skip( 1 ); @@ -1167,7 +1180,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) else { mem->SetTimeFree( timeFree ); - active.emplace( mem->ptr, i ); + active.emplace( ptr, i ); } mem->SetThreadAlloc( threadAlloc ); mem->SetThreadFree( threadFree ); @@ -1182,10 +1195,15 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) for( uint64_t i=0; iSetPtr( ptr ); + mem->SetSize( size ); int64_t timeAlloc, timeFree; f.Read2( timeAlloc, timeFree ); - f.Read( mem->csAlloc ); + Int24 csAlloc; + f.Read( &csAlloc, sizeof( csAlloc ) ); + mem->SetCsAlloc( csAlloc.Val() ); f.Skip( 1 ); f.Read( mem->csFree ); f.Skip( 1 ); @@ -1201,7 +1219,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) else { mem->SetTimeFree( timeFree ); - active.emplace( mem->ptr, i ); + active.emplace( ptr, i ); } mem->SetThreadAlloc( threadAlloc ); mem->SetThreadFree( threadFree ); @@ -1213,12 +1231,18 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) for( uint64_t i=0; i FileVersion( 0, 4, 1 ) ) { - f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) ); + uint64_t size; + f.Read2( ptr, size ); + mem->SetPtr( ptr ); + mem->SetSize( size ); int64_t timeAlloc, timeFree; f.Read2( timeAlloc, timeFree ); - f.Read( mem->csAlloc ); + Int24 csAlloc; + f.Read( &csAlloc, sizeof( csAlloc ) ); + mem->SetCsAlloc( csAlloc.Val() ); f.Skip( 1 ); f.Read( mem->csFree ); f.Skip( 1 ); @@ -1235,10 +1259,15 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) } else { - f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) ); + uint64_t ptr, size; + f.Read2( ptr, size ); + mem->SetPtr( ptr ); + mem->SetSize( size ); int64_t timeAlloc, timeFree; f.Read2( timeAlloc, timeFree ); - f.Read( mem->csAlloc ); + Int24 csAlloc; + f.Read( &csAlloc, sizeof( csAlloc ) ); + mem->SetCsAlloc( csAlloc.Val() ); f.Skip( 1 ); f.Read( mem->csFree ); f.Skip( 1 ); @@ -1267,7 +1296,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) if( mem->TimeFree() < 0 ) { - m_data.memory.active.emplace( mem->ptr, i ); + m_data.memory.active.emplace( ptr, i ); } else { @@ -1293,19 +1322,19 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) if( fileVer >= FileVersion( 0, 5, 9 ) ) { - f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) ); + f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( Int24 ) + sizeof( Int24 ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) ); } else if( fileVer >= FileVersion( 0, 5, 2 ) ) { - f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) ); + f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) ); } else if( fileVer >= FileVersion( 0, 4, 4 ) ) { - f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint16_t ) + sizeof( uint16_t ) ) ); + f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint16_t ) + sizeof( uint16_t ) ) ); } else { - f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + 2 * sizeof( uint64_t ) ) ); + f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + 2 * sizeof( uint64_t ) ) ); } f.Skip( sizeof( MemData::high ) + sizeof( MemData::low ) + sizeof( MemData::usage ) ); @@ -4326,13 +4355,13 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev ) const uint64_t size = lo | ( uint64_t( hi ) << 32 ); auto& mem = m_data.memory.data.push_next(); - mem.ptr = ptr; - mem.size = size; + mem.SetPtr( ptr ); + mem.SetSize( size ); mem.SetTimeAlloc( time ); mem.SetThreadAlloc( CompressThread( ev.thread ) ); mem.SetTimeFree( -1 ); mem.SetThreadFree( 0 ); - mem.csAlloc.SetVal( 0 ); + mem.SetCsAlloc( 0 ); mem.csFree.SetVal( 0 ); const auto low = m_data.memory.low; @@ -4370,7 +4399,7 @@ bool Worker::ProcessMemFree( const QueueMemFree& ev ) auto& mem = m_data.memory.data[it->second]; mem.SetTimeFree( time ); mem.SetThreadFree( CompressThread( ev.thread ) ); - m_data.memory.usage -= mem.size; + m_data.memory.usage -= mem.Size(); m_data.memory.active.erase( it ); MemAllocChanged( time ); @@ -4407,7 +4436,7 @@ void Worker::ProcessCallstackMemory( const QueueCallstackMemory& ev ) auto& mem = m_data.memory.data[m_lastMemActionCallstack]; if( m_lastMemActionWasAlloc ) { - mem.csAlloc.SetVal( m_pendingCallstackId ); + mem.SetCsAlloc( m_pendingCallstackId ); } else { @@ -4757,7 +4786,7 @@ void Worker::ReconstructMemAllocPlot() { if( atime < ftime ) { - usage += int64_t( aptr->size ); + usage += int64_t( aptr->Size() ); assert( usage >= 0 ); if( max < usage ) max = usage; ptr->time = atime; @@ -4769,7 +4798,7 @@ void Worker::ReconstructMemAllocPlot() } else { - usage -= int64_t( mem.data[*fptr].size ); + usage -= int64_t( mem.data[*fptr].Size() ); assert( usage >= 0 ); if( max < usage ) max = usage; ptr->time = ftime; @@ -4786,7 +4815,7 @@ void Worker::ReconstructMemAllocPlot() { assert( aptr->TimeFree() < 0 ); int64_t time = aptr->TimeAlloc(); - usage += int64_t( aptr->size ); + usage += int64_t( aptr->Size() ); assert( usage >= 0 ); if( max < usage ) max = usage; ptr->time = time; @@ -4798,7 +4827,7 @@ void Worker::ReconstructMemAllocPlot() { const auto& memData = mem.data[*fptr]; int64_t time = memData.TimeFree(); - usage -= int64_t( memData.size ); + usage -= int64_t( memData.Size() ); assert( usage >= 0 ); assert( max >= usage ); ptr->time = time; @@ -5532,9 +5561,12 @@ void Worker::Write( FileWrite& f ) f.Write( &sz, sizeof( sz ) ); for( auto& mem : m_data.memory.data ) { - f.Write( &mem.ptr, sizeof( mem.ptr ) ); - f.Write( &mem.size, sizeof( mem.size ) ); - f.Write( &mem.csAlloc, sizeof( mem.csAlloc ) ); + const auto ptr = mem.Ptr(); + const auto size = mem.Size(); + const Int24 csAlloc = mem.CsAlloc(); + f.Write( &ptr, sizeof( ptr ) ); + f.Write( &size, sizeof( size ) ); + f.Write( &csAlloc, sizeof( csAlloc ) ); f.Write( &mem.csFree, sizeof( mem.csFree ) ); int64_t timeAlloc = mem.TimeAlloc();