1
0
mirror of https://github.com/wolfpld/tracy.git synced 2025-03-20 07:40:02 +08:00

Pack time and thread in MemEvent.

This saves 4 bytes per logged memory allocation. Memory savings for
selected traces:

android     2945 MB -> 2766 MB
chicken     2261 MB -> 2245 MB
q3bsp-mt    6085 MB -> 6043 MB
mem         6788 MB -> 6468 MB
This commit is contained in:
Bartosz Taudul 2019-08-15 22:56:55 +02:00
parent 9618ee3581
commit c22c259a13
3 changed files with 191 additions and 111 deletions

View File

@ -155,14 +155,21 @@ static_assert( std::is_standard_layout<GpuEvent>::value, "GpuEvent is not standa
struct MemEvent struct MemEvent
{ {
int64_t TimeAlloc() const { return int64_t( _time_thread_alloc ) >> 16; }
void SetTimeAlloc( int64_t time ) { assert( time < ( 1ll << 47 ) ); _time_thread_alloc = ( _time_thread_alloc & 0xFFFF ) | uint64_t( time << 16 ); }
int64_t TimeFree() const { return int64_t( _time_thread_free ) >> 16; }
void SetTimeFree( int64_t time ) { assert( time < ( 1ll << 47 ) ); _time_thread_free = ( _time_thread_free & 0xFFFF ) | uint64_t( time << 16 ); }
uint16_t ThreadAlloc() const { return uint16_t( _time_thread_alloc ); }
void SetThreadAlloc( uint16_t thread ) { _time_thread_alloc = ( _time_thread_alloc & 0xFFFFFFFFFFFF0000 ) | thread; }
uint16_t ThreadFree() const { return uint16_t( _time_thread_free ); }
void SetThreadFree( uint16_t thread ) { _time_thread_free = ( _time_thread_free & 0xFFFFFFFFFFFF0000 ) | thread; }
uint64_t ptr; uint64_t ptr;
uint64_t size; uint64_t size;
int64_t timeAlloc;
int64_t timeFree;
uint32_t csAlloc; uint32_t csAlloc;
uint32_t csFree; uint32_t csFree;
uint16_t threadAlloc; uint64_t _time_thread_alloc;
uint16_t threadFree; uint64_t _time_thread_free;
}; };
enum { MemEventSize = sizeof( MemEvent ) }; enum { MemEventSize = sizeof( MemEvent ) };

View File

@ -3979,8 +3979,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
{ {
const auto& ev = mem.data[m_memoryAllocInfoWindow]; const auto& ev = mem.data[m_memoryAllocInfoWindow];
const auto tStart = ev.timeAlloc; const auto tStart = ev.TimeAlloc();
const auto tEnd = ev.timeFree < 0 ? m_worker.GetLastTime() : ev.timeFree; const auto tEnd = ev.TimeFree() < 0 ? m_worker.GetLastTime() : ev.TimeFree();
const auto px0 = ( tStart - m_zvStart ) * pxns; const auto px0 = ( tStart - m_zvStart ) * pxns;
const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_zvStart ) * pxns ); const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_zvStart ) * pxns );
@ -3991,8 +3991,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
{ {
const auto& ev = mem.data[m_memoryAllocHover]; const auto& ev = mem.data[m_memoryAllocHover];
const auto tStart = ev.timeAlloc; const auto tStart = ev.TimeAlloc();
const auto tEnd = ev.timeFree < 0 ? m_worker.GetLastTime() : ev.timeFree; const auto tEnd = ev.TimeFree() < 0 ? m_worker.GetLastTime() : ev.TimeFree();
const auto px0 = ( tStart - m_zvStart ) * pxns; const auto px0 = ( tStart - m_zvStart ) * pxns;
const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_zvStart ) * pxns ); const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_zvStart ) * pxns );
@ -4286,8 +4286,8 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint
const MemEvent* ev = nullptr; const MemEvent* ev = nullptr;
if( change > 0 ) if( change > 0 )
{ {
auto it = std::lower_bound( mem.data.begin(), mem.data.end(), item->time, [] ( const auto& lhs, const auto& rhs ) { return lhs.timeAlloc < rhs; } ); auto it = std::lower_bound( mem.data.begin(), mem.data.end(), item->time, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
if( it != mem.data.end() && it->timeAlloc == item->time ) if( it != mem.data.end() && it->TimeAlloc() == item->time )
{ {
ev = it; ev = it;
} }
@ -4295,8 +4295,8 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint
else else
{ {
const auto& data = mem.data; const auto& data = mem.data;
auto it = std::lower_bound( mem.frees.begin(), mem.frees.end(), item->time, [&data] ( const auto& lhs, const auto& rhs ) { return data[lhs].timeFree < rhs; } ); auto it = std::lower_bound( mem.frees.begin(), mem.frees.end(), item->time, [&data] ( const auto& lhs, const auto& rhs ) { return data[lhs].TimeFree() < rhs; } );
if( it != mem.frees.end() && data[*it].timeFree == item->time ) if( it != mem.frees.end() && data[*it].TimeFree() == item->time )
{ {
ev = &data[*it]; ev = &data[*it];
} }
@ -4307,34 +4307,34 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint
TextDisabledUnformatted( "Address:" ); TextDisabledUnformatted( "Address:" );
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text( "0x%" PRIx64, ev->ptr ); ImGui::Text( "0x%" PRIx64, ev->ptr );
TextFocused( "Appeared at", TimeToString( ev->timeAlloc ) ); TextFocused( "Appeared at", TimeToString( ev->TimeAlloc() ) );
if( change > 0 ) if( change > 0 )
{ {
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextDisabled( "(this event)" ); ImGui::TextDisabled( "(this event)" );
} }
if( ev->timeFree < 0 ) if( ev->TimeFree() < 0 )
{ {
ImGui::TextUnformatted( "Allocation still active" ); ImGui::TextUnformatted( "Allocation still active" );
} }
else else
{ {
TextFocused( "Freed at", TimeToString( ev->timeFree ) ); TextFocused( "Freed at", TimeToString( ev->TimeFree() ) );
if( change < 0 ) if( change < 0 )
{ {
ImGui::SameLine(); ImGui::SameLine();
TextDisabledUnformatted( "(this event)" ); TextDisabledUnformatted( "(this event)" );
} }
TextFocused( "Duration:", TimeToString( ev->timeFree - ev->timeAlloc ) ); TextFocused( "Duration:", TimeToString( ev->TimeFree() - ev->TimeAlloc() ) );
} }
uint64_t tid; uint64_t tid;
if( change > 0 ) if( change > 0 )
{ {
tid = m_worker.DecompressThread( ev->threadAlloc ); tid = m_worker.DecompressThread( ev->ThreadAlloc() );
} }
else else
{ {
tid = m_worker.DecompressThread( ev->threadFree ); tid = m_worker.DecompressThread( ev->ThreadFree() );
} }
TextFocused( "Thread:", m_worker.GetThreadString( tid ) ); TextFocused( "Thread:", m_worker.GetThreadString( tid ) );
ImGui::SameLine(); ImGui::SameLine();
@ -4852,11 +4852,12 @@ void View::DrawZoneInfoWindow()
{ {
const auto thread = m_worker.CompressThread( tid ); const auto thread = m_worker.CompressThread( tid );
auto ait = std::lower_bound( mem.data.begin(), mem.data.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.timeAlloc < r; } ); // TODO: use ait, fit as begin for aend, fend search
const auto aend = std::upper_bound( mem.data.begin(), mem.data.end(), end, [] ( const auto& l, const auto& r ) { return l < r.timeAlloc; } ); auto ait = std::lower_bound( mem.data.begin(), mem.data.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.TimeAlloc() < r; } );
const auto aend = std::upper_bound( mem.data.begin(), mem.data.end(), end, [] ( const auto& l, const auto& r ) { return l < r.TimeAlloc(); } );
auto fit = std::lower_bound( mem.frees.begin(), mem.frees.end(), ev.Start(), [&mem] ( const auto& l, const auto& r ) { return mem.data[l].timeFree < r; } ); auto fit = std::lower_bound( mem.frees.begin(), mem.frees.end(), ev.Start(), [&mem] ( const auto& l, const auto& r ) { return mem.data[l].TimeFree() < r; } );
const auto fend = std::upper_bound( mem.frees.begin(), mem.frees.end(), end, [&mem] ( const auto& l, const auto& r ) { return l < mem.data[r].timeFree; } ); const auto fend = std::upper_bound( mem.frees.begin(), mem.frees.end(), end, [&mem] ( const auto& l, const auto& r ) { return l < mem.data[r].TimeFree(); } );
const auto aDist = std::distance( ait, aend ); const auto aDist = std::distance( ait, aend );
const auto fDist = std::distance( fit, fend ); const auto fDist = std::distance( fit, fend );
@ -4876,7 +4877,7 @@ void View::DrawZoneInfoWindow()
while( ait != aend ) while( ait != aend )
{ {
if( ait->threadAlloc == thread ) if( ait->ThreadAlloc() == thread )
{ {
cAlloc += ait->size; cAlloc += ait->size;
nAlloc++; nAlloc++;
@ -4885,7 +4886,7 @@ void View::DrawZoneInfoWindow()
} }
while( fit != fend ) while( fit != fend )
{ {
if( mem.data[*fit].threadFree == thread ) if( mem.data[*fit].ThreadFree() == thread )
{ {
cFree += mem.data[*fit].size; cFree += mem.data[*fit].size;
nFree++; nFree++;
@ -4923,7 +4924,7 @@ void View::DrawZoneInfoWindow()
auto it = ait2; auto it = ait2;
while( it != aend ) while( it != aend )
{ {
if( it->threadAlloc == thread ) if( it->ThreadAlloc() == thread )
{ {
v.emplace_back( it ); v.emplace_back( it );
} }
@ -4932,7 +4933,7 @@ void View::DrawZoneInfoWindow()
while( fit2 != fend ) while( fit2 != fend )
{ {
const auto ptr = &mem.data[*fit2++]; const auto ptr = &mem.data[*fit2++];
if( ptr->threadFree == thread ) if( ptr->ThreadFree() == thread )
{ {
if( ptr < ait2 || ptr >= aend ) if( ptr < ait2 || ptr >= aend )
{ {
@ -4940,7 +4941,7 @@ void View::DrawZoneInfoWindow()
} }
} }
} }
pdqsort_branchless( v.begin(), v.end(), [] ( const auto& l, const auto& r ) { return l->timeAlloc < r->timeAlloc; } ); pdqsort_branchless( v.begin(), v.end(), [] ( const auto& l, const auto& r ) { return l->TimeAlloc() < r->TimeAlloc(); } );
ListMemData<decltype( v.begin() )>( v.begin(), v.end(), []( auto& v ) { ListMemData<decltype( v.begin() )>( v.begin(), v.end(), []( auto& v ) {
ImGui::Text( "0x%" PRIx64, (*v)->ptr ); ImGui::Text( "0x%" PRIx64, (*v)->ptr );
@ -8976,8 +8977,8 @@ void View::DrawMemoryAllocWindow()
const auto& mem = m_worker.GetMemData(); const auto& mem = m_worker.GetMemData();
const auto& ev = mem.data[m_memoryAllocInfoWindow]; const auto& ev = mem.data[m_memoryAllocInfoWindow];
const auto tidAlloc = m_worker.DecompressThread( ev.threadAlloc ); const auto tidAlloc = m_worker.DecompressThread( ev.ThreadAlloc() );
const auto tidFree = m_worker.DecompressThread( ev.threadFree ); const auto tidFree = m_worker.DecompressThread( ev.ThreadFree() );
int idx = 0; int idx = 0;
#ifdef TRACY_EXTENDED_FONT #ifdef TRACY_EXTENDED_FONT
@ -8986,7 +8987,7 @@ void View::DrawMemoryAllocWindow()
if( ImGui::Button( "Zoom to allocation" ) ) if( ImGui::Button( "Zoom to allocation" ) )
#endif #endif
{ {
ZoomToRange( ev.timeAlloc, ev.timeFree >= 0 ? ev.timeFree : m_worker.GetLastTime() ); ZoomToRange( ev.TimeAlloc(), ev.TimeFree() >= 0 ? ev.TimeFree() : m_worker.GetLastTime() );
} }
char buf[64]; char buf[64];
@ -8999,8 +9000,8 @@ void View::DrawMemoryAllocWindow()
ImGui::TextDisabled( "(%s bytes)", RealToString( ev.size, true ) ); ImGui::TextDisabled( "(%s bytes)", RealToString( ev.size, true ) );
} }
ImGui::Separator(); ImGui::Separator();
TextFocused( "Appeared at", TimeToString( ev.timeAlloc ) ); TextFocused( "Appeared at", TimeToString( ev.TimeAlloc() ) );
if( ImGui::IsItemClicked() ) CenterAtTime( ev.timeAlloc ); if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeAlloc() );
ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
TextFocused( "Thread:", m_worker.GetThreadString( tidAlloc ) ); TextFocused( "Thread:", m_worker.GetThreadString( tidAlloc ) );
ImGui::SameLine(); ImGui::SameLine();
@ -9010,14 +9011,14 @@ void View::DrawMemoryAllocWindow()
ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
SmallCallstackButton( "Call stack", ev.csAlloc, idx ); SmallCallstackButton( "Call stack", ev.csAlloc, idx );
} }
if( ev.timeFree < 0 ) if( ev.TimeFree() < 0 )
{ {
TextDisabledUnformatted( "Allocation still active" ); TextDisabledUnformatted( "Allocation still active" );
} }
else else
{ {
TextFocused( "Freed at", TimeToString( ev.timeFree ) ); TextFocused( "Freed at", TimeToString( ev.TimeFree() ) );
if( ImGui::IsItemClicked() ) CenterAtTime( ev.timeFree ); if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeFree() );
ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
TextFocused( "Thread:", m_worker.GetThreadString( tidFree ) ); TextFocused( "Thread:", m_worker.GetThreadString( tidFree ) );
ImGui::SameLine(); ImGui::SameLine();
@ -9027,12 +9028,12 @@ void View::DrawMemoryAllocWindow()
ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
SmallCallstackButton( "Call stack", ev.csFree, idx ); SmallCallstackButton( "Call stack", ev.csFree, idx );
} }
TextFocused( "Duration:", TimeToString( ev.timeFree - ev.timeAlloc ) ); TextFocused( "Duration:", TimeToString( ev.TimeFree() - ev.TimeAlloc() ) );
} }
ImGui::Separator(); ImGui::Separator();
auto zoneAlloc = FindZoneAtTime( tidAlloc, ev.timeAlloc ); auto zoneAlloc = FindZoneAtTime( tidAlloc, ev.TimeAlloc() );
if( zoneAlloc ) if( zoneAlloc )
{ {
const auto& srcloc = m_worker.GetSourceLocation( zoneAlloc->SrcLoc() ); const auto& srcloc = m_worker.GetSourceLocation( zoneAlloc->SrcLoc() );
@ -9056,9 +9057,9 @@ void View::DrawMemoryAllocWindow()
} }
} }
if( ev.timeFree >= 0 ) if( ev.TimeFree() >= 0 )
{ {
auto zoneFree = FindZoneAtTime( tidFree, ev.timeFree ); auto zoneFree = FindZoneAtTime( tidFree, ev.TimeFree() );
if( zoneFree ) if( zoneFree )
{ {
const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() ); const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() );
@ -10166,7 +10167,7 @@ void View::ListMemData( T ptr, T end, std::function<void(T&)> DrawAddress, const
} }
if( ImGui::IsItemClicked( 2 ) ) if( ImGui::IsItemClicked( 2 ) )
{ {
ZoomToRange( v->timeAlloc, v->timeFree >= 0 ? v->timeFree : m_worker.GetLastTime() ); ZoomToRange( v->TimeAlloc(), v->TimeFree() >= 0 ? v->TimeFree() : m_worker.GetLastTime() );
} }
if( ImGui::IsItemHovered() ) if( ImGui::IsItemHovered() )
{ {
@ -10177,38 +10178,38 @@ void View::ListMemData( T ptr, T end, std::function<void(T&)> DrawAddress, const
ImGui::TextUnformatted( MemSizeToString( v->size ) ); ImGui::TextUnformatted( MemSizeToString( v->size ) );
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::PushID( idx++ ); ImGui::PushID( idx++ );
if( ImGui::Selectable( TimeToString( v->timeAlloc - startTime ) ) ) if( ImGui::Selectable( TimeToString( v->TimeAlloc() - startTime ) ) )
{ {
CenterAtTime( v->timeAlloc ); CenterAtTime( v->TimeAlloc() );
} }
ImGui::PopID(); ImGui::PopID();
ImGui::NextColumn(); ImGui::NextColumn();
if( v->timeFree < 0 ) if( v->TimeFree() < 0 )
{ {
TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), TimeToString( m_worker.GetLastTime() - v->timeAlloc ) ); TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), TimeToString( m_worker.GetLastTime() - v->TimeAlloc() ) );
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::TextUnformatted( m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); ImGui::TextUnformatted( m_worker.GetThreadString( m_worker.DecompressThread( v->ThreadAlloc() ) ) );
} }
else else
{ {
ImGui::PushID( idx++ ); ImGui::PushID( idx++ );
if( ImGui::Selectable( TimeToString( v->timeFree - v->timeAlloc ) ) ) if( ImGui::Selectable( TimeToString( v->TimeFree() - v->TimeAlloc() ) ) )
{ {
CenterAtTime( v->timeFree ); CenterAtTime( v->TimeFree() );
} }
ImGui::PopID(); ImGui::PopID();
ImGui::NextColumn(); ImGui::NextColumn();
if( v->threadAlloc == v->threadFree ) if( v->ThreadAlloc() == v->ThreadFree() )
{ {
ImGui::TextUnformatted( m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); ImGui::TextUnformatted( m_worker.GetThreadString( m_worker.DecompressThread( v->ThreadAlloc() ) ) );
} }
else else
{ {
ImGui::Text( "%s / %s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ), m_worker.GetThreadString( m_worker.DecompressThread( v->threadFree ) ) ); ImGui::Text( "%s / %s", m_worker.GetThreadString( m_worker.DecompressThread( v->ThreadAlloc() ) ), m_worker.GetThreadString( m_worker.DecompressThread( v->ThreadFree() ) ) );
} }
} }
ImGui::NextColumn(); ImGui::NextColumn();
auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadAlloc ), v->timeAlloc ); auto zone = FindZoneAtTime( m_worker.DecompressThread( v->ThreadAlloc() ), v->TimeAlloc() );
if( !zone ) if( !zone )
{ {
ImGui::TextUnformatted( "-" ); ImGui::TextUnformatted( "-" );
@ -10236,13 +10237,13 @@ void View::ListMemData( T ptr, T end, std::function<void(T&)> DrawAddress, const
} }
} }
ImGui::NextColumn(); ImGui::NextColumn();
if( v->timeFree < 0 ) if( v->TimeFree() < 0 )
{ {
TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "active" ); TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "active" );
} }
else else
{ {
auto zoneFree = FindZoneAtTime( m_worker.DecompressThread( v->threadFree ), v->timeFree ); auto zoneFree = FindZoneAtTime( m_worker.DecompressThread( v->ThreadFree() ), v->TimeFree() );
if( !zoneFree ) if( !zoneFree )
{ {
ImGui::TextUnformatted( "-" ); ImGui::TextUnformatted( "-" );
@ -10343,8 +10344,8 @@ flat_hash_map<uint32_t, View::PathData, nohash<uint32_t>> View::GetCallstackPath
for( auto& ev : mem.data ) for( auto& ev : mem.data )
{ {
if( ev.csAlloc == 0 ) continue; if( ev.csAlloc == 0 ) continue;
if( ev.timeAlloc >= zvMid ) continue; if( ev.TimeAlloc() >= zvMid ) continue;
if( onlyActive && ev.timeFree >= 0 && ev.timeFree < zvMid ) continue; if( onlyActive && ev.TimeFree() >= 0 && ev.TimeFree() < zvMid ) continue;
auto it = pathSum.find( ev.csAlloc ); auto it = pathSum.find( ev.csAlloc );
if( it == pathSum.end() ) if( it == pathSum.end() )
@ -10363,7 +10364,7 @@ flat_hash_map<uint32_t, View::PathData, nohash<uint32_t>> View::GetCallstackPath
for( auto& ev : mem.data ) for( auto& ev : mem.data )
{ {
if( ev.csAlloc == 0 ) continue; if( ev.csAlloc == 0 ) continue;
if( onlyActive && ev.timeFree >= 0 ) continue; if( onlyActive && ev.TimeFree() >= 0 ) continue;
auto it = pathSum.find( ev.csAlloc ); auto it = pathSum.find( ev.csAlloc );
if( it == pathSum.end() ) if( it == pathSum.end() )
@ -10589,18 +10590,18 @@ std::vector<MemoryPage> View::GetMemoryPages() const
if( m_memInfo.restrictTime ) if( m_memInfo.restrictTime )
{ {
const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2;
auto end = std::upper_bound( mem.data.begin(), mem.data.end(), zvMid, []( const auto& lhs, const auto& rhs ) { return lhs < rhs.timeAlloc; } ); auto end = std::upper_bound( mem.data.begin(), mem.data.end(), zvMid, []( const auto& lhs, const auto& rhs ) { return lhs < rhs.TimeAlloc(); } );
for( auto it = mem.data.begin(); it != end; ++it ) for( auto it = mem.data.begin(); it != end; ++it )
{ {
auto& alloc = *it; auto& alloc = *it;
const auto a0 = alloc.ptr - memlow; const auto a0 = alloc.ptr - memlow;
const auto a1 = a0 + alloc.size; const auto a1 = a0 + alloc.size;
int8_t val = alloc.timeFree < 0 ? int8_t val = alloc.TimeFree() < 0 ?
int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeAlloc ) >> 24 ) ) ) : int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.TimeAlloc() ) >> 24 ) ) ) :
( alloc.timeFree > zvMid ? ( alloc.TimeFree() > zvMid ?
int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeAlloc ) >> 24 ) ) ) : int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.TimeAlloc() ) >> 24 ) ) ) :
int8_t( -std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeFree ) >> 24 ) ) ) ); int8_t( -std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.TimeFree() ) >> 24 ) ) ) );
const auto c0 = a0 >> ChunkBits; const auto c0 = a0 >> ChunkBits;
const auto c1 = a1 >> ChunkBits; const auto c1 = a1 >> ChunkBits;
@ -10615,9 +10616,9 @@ std::vector<MemoryPage> View::GetMemoryPages() const
{ {
const auto a0 = alloc.ptr - memlow; const auto a0 = alloc.ptr - memlow;
const auto a1 = a0 + alloc.size; const auto a1 = a0 + alloc.size;
const int8_t val = alloc.timeFree < 0 ? 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.TimeAlloc() ) ) >> 24 ) ) ) :
int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.timeFree ) ) >> 24 ) ) ); int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeFree() ) ) >> 24 ) ) );
const auto c0 = a0 >> ChunkBits; const auto c0 = a0 >> ChunkBits;
const auto c1 = a1 >> ChunkBits; const auto c1 = a1 >> ChunkBits;
@ -10713,7 +10714,7 @@ void View::DrawMemory()
{ {
for( auto& v : mem.data ) 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 ); match.emplace_back( &v );
} }
@ -10766,7 +10767,7 @@ void View::DrawMemory()
{ {
for( auto& v : mem.data ) for( auto& v : mem.data )
{ {
if( v.timeAlloc < zvMid && ( v.timeFree > zvMid || v.timeFree < 0 ) ) if( v.TimeAlloc() < zvMid && ( v.TimeFree() > zvMid || v.TimeFree() < 0 ) )
{ {
items.emplace_back( &v ); items.emplace_back( &v );
total += v.size; total += v.size;
@ -10780,7 +10781,7 @@ void View::DrawMemory()
{ {
items.emplace_back( ptr + v.second ); items.emplace_back( ptr + v.second );
} }
pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->TimeAlloc() < rhs->TimeAlloc(); } );
total = mem.usage; total = mem.usage;
} }

View File

@ -1042,8 +1042,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed ); s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
size_t fidx = 0; size_t fidx = 0;
int64_t refTime = 0; int64_t refTime = 0;
if( fileVer <= FileVersion( 0, 5, 2 ) ) refTime = -m_data.baseTime; if( fileVer >= FileVersion( 0, 5, 2 ) )
if( fileVer >= FileVersion( 0, 4, 4 ) )
{ {
auto& frees = m_data.memory.frees; auto& frees = m_data.memory.frees;
auto& active = m_data.memory.active; auto& active = m_data.memory.active;
@ -1051,53 +1050,117 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
for( uint64_t i=0; i<sz; i++ ) for( uint64_t i=0; i<sz; i++ )
{ {
s_loadProgress.subProgress.store( i, std::memory_order_relaxed ); s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + sizeof( MemEvent::threadAlloc ) + sizeof( MemEvent::threadFree ) ); f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) );
refTime += mem->timeAlloc; int64_t timeAlloc, timeFree;
mem->timeAlloc = refTime; uint16_t threadAlloc, threadFree;
if( mem->timeFree >= 0 ) f.Read2( timeAlloc, timeFree );
f.Read2( threadAlloc, threadFree );
refTime += timeAlloc;
mem->SetTimeAlloc( refTime );
if( timeFree >= 0 )
{ {
mem->timeFree += refTime; mem->SetTimeFree( timeFree + refTime );
frees[fidx++] = i; frees[fidx++] = i;
} }
else else
{ {
mem->SetTimeFree( timeFree );
active.emplace( mem->ptr, i ); active.emplace( mem->ptr, i );
} }
mem->SetThreadAlloc( threadAlloc );
mem->SetThreadFree( threadFree );
mem++;
}
}
else if( fileVer >= FileVersion( 0, 4, 4 ) )
{
refTime = -m_data.baseTime;
auto& frees = m_data.memory.frees;
auto& active = m_data.memory.active;
for( uint64_t i=0; i<sz; i++ )
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) );
int64_t timeAlloc, timeFree;
f.Read2( timeAlloc, timeFree );
f.Read( &mem->csAlloc, sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) );
uint16_t threadAlloc, threadFree;
f.Read2( threadAlloc, threadFree );
refTime += timeAlloc;
mem->SetTimeAlloc( refTime );
if( timeFree >= 0 )
{
mem->SetTimeFree( timeFree + refTime );
frees[fidx++] = i;
}
else
{
mem->SetTimeFree( timeFree );
active.emplace( mem->ptr, i );
}
mem->SetThreadAlloc( threadAlloc );
mem->SetThreadFree( threadFree );
mem++; mem++;
} }
} }
else else
{ {
refTime = -m_data.baseTime;
for( uint64_t i=0; i<sz; i++ ) for( uint64_t i=0; i<sz; i++ )
{ {
s_loadProgress.subProgress.store( i, std::memory_order_relaxed ); s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
if( fileVer > FileVersion( 0, 4, 1 ) ) if( fileVer > FileVersion( 0, 4, 1 ) )
{ {
f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) ); f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) );
refTime += mem->timeAlloc; int64_t timeAlloc, timeFree;
mem->timeAlloc = refTime; f.Read2( timeAlloc, timeFree );
if( mem->timeFree >= 0 ) mem->timeFree += refTime; f.Read( &mem->csAlloc, sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) );
uint16_t threadAlloc, threadFree;
f.Read2( threadAlloc, threadFree );
refTime += timeAlloc;
mem->SetTimeAlloc( refTime );
if( timeFree >= 0 )
{
mem->SetTimeFree( timeFree + refTime );
}
else
{
mem->SetTimeFree( timeFree );
}
} }
else else
{ {
f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) ); f.Read( mem, sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) );
mem->timeAlloc -= m_data.baseTime; int64_t timeAlloc, timeFree;
mem->timeFree -= m_data.baseTime; f.Read2( timeAlloc, timeFree );
f.Read( &mem->csAlloc, sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) );
uint16_t threadAlloc, threadFree;
f.Read2( threadAlloc, threadFree );
mem->SetTimeAlloc( timeAlloc - m_data.baseTime );
if( timeFree >= 0 )
{
mem->SetTimeFree( timeFree - m_data.baseTime );
}
else
{
mem->SetTimeFree( timeFree );
}
} }
uint64_t t0, t1; uint64_t t0, t1;
f.Read2( t0, t1 ); f.Read2( t0, t1 );
mem->threadAlloc = CompressThread( t0 ); mem->SetThreadAlloc( CompressThread( t0 ) );
if( t0 == t1 ) if( t0 == t1 )
{ {
mem->threadFree = mem->threadAlloc; mem->SetThreadFree( mem->ThreadAlloc() );
} }
else else
{ {
mem->threadFree = CompressThread( t1 ); mem->SetThreadFree( CompressThread( t1 ) );
} }
if( mem->timeFree < 0 ) if( mem->TimeFree() < 0 )
{ {
m_data.memory.active.emplace( mem->ptr, i ); m_data.memory.active.emplace( mem->ptr, i );
} }
@ -1123,17 +1186,21 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
{ {
f.Skip( 2 * sizeof( uint64_t ) ); f.Skip( 2 * sizeof( uint64_t ) );
if( fileVer >= FileVersion( 0, 4, 4 ) ) if( fileVer >= FileVersion( 0, 5, 2 ) )
{ {
f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + sizeof( MemEvent::threadAlloc ) + sizeof( MemEvent::threadFree ) ) ); f.Skip( sz * ( sizeof( MemEvent::ptr ) + + sizeof( MemEvent::size ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + sizeof( MemEvent::_time_thread_alloc ) + sizeof( MemEvent::_time_thread_free ) ) );
}
else if( fileVer >= FileVersion( 0, 4, 4 ) )
{
f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + sizeof( uint16_t ) + sizeof( uint16_t ) ) );
} }
else if( fileVer > FileVersion( 0, 4, 1 ) ) else if( fileVer > FileVersion( 0, 4, 1 ) )
{ {
f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + 2 * sizeof( uint64_t ) ) ); f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + 2 * sizeof( uint64_t ) ) );
} }
else else
{ {
f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( MemEvent::timeAlloc ) + sizeof( MemEvent::timeFree ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + 2 * sizeof( uint64_t ) ) ); f.Skip( sz * ( sizeof( MemEvent::ptr ) + sizeof( MemEvent::size ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( MemEvent::csAlloc ) + sizeof( MemEvent::csFree ) + 2 * sizeof( uint64_t ) ) );
} }
f.Skip( sizeof( MemData::high ) + sizeof( MemData::low ) + sizeof( MemData::usage ) ); f.Skip( sizeof( MemData::high ) + sizeof( MemData::low ) + sizeof( MemData::usage ) );
@ -3646,7 +3713,7 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev )
NoticeThread( ev.thread ); NoticeThread( ev.thread );
assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() );
assert( m_data.memory.data.empty() || m_data.memory.data.back().timeAlloc <= time ); assert( m_data.memory.data.empty() || m_data.memory.data.back().TimeAlloc() <= time );
m_data.memory.active.emplace( ev.ptr, m_data.memory.data.size() ); m_data.memory.active.emplace( ev.ptr, m_data.memory.data.size() );
@ -3660,10 +3727,10 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev )
auto& mem = m_data.memory.data.push_next(); auto& mem = m_data.memory.data.push_next();
mem.ptr = ptr; mem.ptr = ptr;
mem.size = size; mem.size = size;
mem.timeAlloc = time; mem.SetTimeAlloc( time );
mem.threadAlloc = CompressThread( ev.thread ); mem.SetThreadAlloc( CompressThread( ev.thread ) );
mem.timeFree = -1; mem.SetTimeFree( -1 );
mem.threadFree = 0; mem.SetThreadFree( 0 );
mem.csAlloc = 0; mem.csAlloc = 0;
mem.csFree = 0; mem.csFree = 0;
@ -3698,8 +3765,8 @@ bool Worker::ProcessMemFree( const QueueMemFree& ev )
m_data.memory.frees.push_back( it->second ); m_data.memory.frees.push_back( it->second );
auto& mem = m_data.memory.data[it->second]; auto& mem = m_data.memory.data[it->second];
mem.timeFree = time; mem.SetTimeFree( time );
mem.threadFree = CompressThread( ev.thread ); mem.SetThreadFree( CompressThread( ev.thread ) );
m_data.memory.usage -= mem.size; m_data.memory.usage -= mem.size;
m_data.memory.active.erase( it ); m_data.memory.active.erase( it );
@ -3963,9 +4030,9 @@ void Worker::ReconstructMemAllocPlot()
{ {
auto& mem = m_data.memory; auto& mem = m_data.memory;
#ifdef MY_LIBCPP_SUCKS #ifdef MY_LIBCPP_SUCKS
pdqsort_branchless( mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].timeFree < mem.data[rhs].timeFree; } ); pdqsort_branchless( mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );
#else #else
std::sort( std::execution::par_unseq, mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].timeFree < mem.data[rhs].timeFree; } ); std::sort( std::execution::par_unseq, mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );
#endif #endif
const auto psz = mem.data.size() + mem.frees.size() + 1; const auto psz = mem.data.size() + mem.frees.size() + 1;
@ -3995,8 +4062,8 @@ void Worker::ReconstructMemAllocPlot()
if( aptr != aend && fptr != fend ) if( aptr != aend && fptr != fend )
{ {
auto atime = aptr->timeAlloc; auto atime = aptr->TimeAlloc();
auto ftime = mem.data[*fptr].timeFree; auto ftime = mem.data[*fptr].TimeFree();
for(;;) for(;;)
{ {
@ -4010,7 +4077,7 @@ void Worker::ReconstructMemAllocPlot()
ptr++; ptr++;
aptr++; aptr++;
if( aptr == aend ) break; if( aptr == aend ) break;
atime = aptr->timeAlloc; atime = aptr->TimeAlloc();
} }
else else
{ {
@ -4022,15 +4089,15 @@ void Worker::ReconstructMemAllocPlot()
ptr++; ptr++;
fptr++; fptr++;
if( fptr == fend ) break; if( fptr == fend ) break;
ftime = mem.data[*fptr].timeFree; ftime = mem.data[*fptr].TimeFree();
} }
} }
} }
while( aptr != aend ) while( aptr != aend )
{ {
assert( aptr->timeFree < 0 ); assert( aptr->TimeFree() < 0 );
int64_t time = aptr->timeAlloc; int64_t time = aptr->TimeAlloc();
usage += int64_t( aptr->size ); usage += int64_t( aptr->size );
assert( usage >= 0 ); assert( usage >= 0 );
if( max < usage ) max = usage; if( max < usage ) max = usage;
@ -4042,7 +4109,7 @@ void Worker::ReconstructMemAllocPlot()
while( fptr != fend ) while( fptr != fend )
{ {
const auto& memData = mem.data[*fptr]; const auto& memData = mem.data[*fptr];
int64_t time = memData.timeFree; int64_t time = memData.TimeFree();
usage -= int64_t( memData.size ); usage -= int64_t( memData.size );
assert( usage >= 0 ); assert( usage >= 0 );
assert( max >= usage ); assert( max >= usage );
@ -4654,13 +4721,18 @@ void Worker::Write( FileWrite& f )
{ {
f.Write( &mem.ptr, sizeof( mem.ptr ) ); f.Write( &mem.ptr, sizeof( mem.ptr ) );
f.Write( &mem.size, sizeof( mem.size ) ); f.Write( &mem.size, sizeof( mem.size ) );
WriteTimeOffset( f, refTime, mem.timeAlloc );
int64_t freeOffset = mem.timeFree < 0 ? mem.timeFree : mem.timeFree - mem.timeAlloc;
f.Write( &freeOffset, sizeof( freeOffset ) );
f.Write( &mem.csAlloc, sizeof( mem.csAlloc ) ); f.Write( &mem.csAlloc, sizeof( mem.csAlloc ) );
f.Write( &mem.csFree, sizeof( mem.csFree ) ); f.Write( &mem.csFree, sizeof( mem.csFree ) );
f.Write( &mem.threadAlloc, sizeof( mem.threadAlloc ) );
f.Write( &mem.threadFree, sizeof( mem.threadFree ) ); int64_t timeAlloc = mem.TimeAlloc();
uint16_t threadAlloc = mem.ThreadAlloc();
int64_t timeFree = mem.TimeFree();
uint16_t threadFree = mem.ThreadFree();
WriteTimeOffset( f, refTime, timeAlloc );
int64_t freeOffset = timeFree < 0 ? timeFree : timeFree - timeAlloc;
f.Write( &freeOffset, sizeof( freeOffset ) );
f.Write( &threadAlloc, sizeof( threadAlloc ) );
f.Write( &threadFree, sizeof( threadFree ) );
} }
f.Write( &m_data.memory.high, sizeof( m_data.memory.high ) ); f.Write( &m_data.memory.high, sizeof( m_data.memory.high ) );
f.Write( &m_data.memory.low, sizeof( m_data.memory.low ) ); f.Write( &m_data.memory.low, sizeof( m_data.memory.low ) );