From d228bcb622bf74f9d52902eb360d84a696a68fed Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 29 Sep 2019 20:32:42 +0200 Subject: [PATCH] Pack StringIdx in 24 bits. This reduces ZoneEvent size from 32 to 30 bytes. Memory usage reduction on selected traces (sizes in MB): big 9902 -> 9527 (96%) chicken 2172 -> 2107 (97%) ctx-big 311 -> 309 (99%) drl-l-b 1570 -> 1479 (94%) long 5496 -> 5412 (98%) mem 6468 -> 6468 (100%) q3bsp-mt 5784 -> 5592 (96%) selfprofile 1486 -> 1443 (97%) --- server/TracyEvent.hpp | 46 ++++++++++---- server/TracyVersion.hpp | 2 +- server/TracyView.cpp | 20 +++--- server/TracyWorker.cpp | 138 ++++++++++++++++++++++++++++++++-------- server/TracyWorker.hpp | 8 +-- 5 files changed, 159 insertions(+), 55 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index b4a59bd8..44e50666 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -41,27 +41,45 @@ struct StringRef }; }; -struct StringIdx +class StringIdx { - StringIdx() : __data( 0 ) {} - StringIdx( uint32_t _idx ) - : __data( 0 ) +public: + StringIdx() { memset( m_idx, 0, sizeof( m_idx ) ); } + StringIdx( uint32_t idx ) { - idx = _idx; - active = 1; + SetIdx( idx ); } - union + void SetIdx( uint32_t idx ) { - struct - { - uint32_t idx : 31; - uint32_t active : 1; - }; - uint32_t __data; - }; + idx++; + memcpy( m_idx, &idx, 3 ); + } + + uint32_t Idx() const + { + uint32_t idx = 0; + memcpy( &idx, m_idx, 3 ); + return idx - 1; + } + + bool Active() const + { + uint32_t zero = 0; + return memcmp( m_idx, &zero, 3 ) != 0; + } + +private: + uint8_t m_idx[3]; }; +struct __StringIdxOld +{ + uint32_t idx : 31; + uint32_t active : 1; +}; + + struct SourceLocation { StringRef name; diff --git a/server/TracyVersion.hpp b/server/TracyVersion.hpp index 9cb53782..677569a0 100644 --- a/server/TracyVersion.hpp +++ b/server/TracyVersion.hpp @@ -7,7 +7,7 @@ namespace Version { enum { Major = 0 }; enum { Minor = 5 }; -enum { Patch = 7 }; +enum { Patch = 8 }; } } diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 6511a6ac..d13c1491 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -2996,7 +2996,7 @@ int View::DrawZoneLevel( const Vector& vec, bool hover, double pxns, { const auto color = GetZoneColor( ev, tid, depth ); const char* zoneName = m_worker.GetZoneName( ev ); - int dmul = ev.text.active ? 2 : 1; + int dmul = ev.text.Active() ? 2 : 1; if( ev.child >= 0 ) { @@ -5336,7 +5336,7 @@ void View::DrawZoneInfoWindow() auto threadData = GetZoneThreadData( ev ); assert( threadData ); const auto tid = threadData->id; - if( ev.name.active ) + if( ev.name.Active() ) { if( m_bigFont ) ImGui::PushFont( m_bigFont ); TextFocused( "Zone name:", m_worker.GetString( ev.name ) ); @@ -5371,7 +5371,7 @@ void View::DrawZoneInfoWindow() ImGui::TextDisabled( "(%s)", RealToString( tid, true ) ); ImGui::SameLine(); SmallColorBox( GetThreadColor( tid, 0 ) ); - if( ev.text.active ) + if( ev.text.Active() ) { TextFocused( "User text:", m_worker.GetString( ev.text ) ); dmul++; @@ -7237,7 +7237,7 @@ uint64_t View::GetSelectionTarget( const Worker::ZoneThreadData& ev, FindZone::G case FindZone::GroupBy::Thread: return ev.Thread(); case FindZone::GroupBy::UserText: - return ev.Zone()->text.active ? ev.Zone()->text.idx : std::numeric_limits::max(); + return ev.Zone()->text.Active() ? ev.Zone()->text.Idx() : std::numeric_limits::max(); case FindZone::GroupBy::Callstack: return ev.Zone()->callstack; default: @@ -8265,7 +8265,7 @@ void View::DrawFindZone() group = &m_findZone.groups[ev.Thread()]; break; case FindZone::GroupBy::UserText: - group = &m_findZone.groups[ev.Zone()->text.active ? ev.Zone()->text.idx : std::numeric_limits::max()]; + group = &m_findZone.groups[ev.Zone()->text.Active() ? ev.Zone()->text.Idx() : std::numeric_limits::max()]; break; case FindZone::GroupBy::Callstack: group = &m_findZone.groups[ev.Zone()->callstack]; @@ -8548,7 +8548,7 @@ void View::DrawZoneList( const Vector& zones ) break; case FindZone::TableSortBy::Name: pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) { - if( lhs->name.active != rhs->name.active ) return lhs->name.active > rhs->name.active; + if( lhs->name.Active() != rhs->name.Active() ) return lhs->name.Active() > rhs->name.Active(); return strcmp( m_worker.GetString( lhs->name ), m_worker.GetString( rhs->name ) ) < 0; } ); break; @@ -8592,7 +8592,7 @@ void View::DrawZoneList( const Vector& zones ) ImGui::NextColumn(); ImGui::TextUnformatted( TimeToString( timespan ) ); ImGui::NextColumn(); - if( ev->name.active ) + if( ev->name.Active() ) { ImGui::TextUnformatted( m_worker.GetString( ev->name ) ); } @@ -11508,7 +11508,7 @@ static tracy_force_inline CallstackFrameTree* GetFrameTreeItemGroup( flat_hash_m { auto& frameData = *worker.GetCallstackFrame( idx ); auto& frame = frameData.data[frameData.size-1]; - auto fidx = frame.name.idx; + auto fidx = frame.name.Idx(); auto it = tree.find( fidx ); if( it == tree.end() ) @@ -12562,7 +12562,7 @@ void View::ZoneTooltip( const ZoneEvent& ev ) const auto selftime = GetZoneSelfTime( ev ); ImGui::BeginTooltip(); - if( ev.name.active ) + if( ev.name.Active() ) { ImGui::TextUnformatted( m_worker.GetString( ev.name ) ); } @@ -12610,7 +12610,7 @@ void View::ZoneTooltip( const ZoneEvent& ev ) TextFocused( "Running state regions:", RealToString( cnt, true ) ); } } - if( ev.text.active ) + if( ev.text.Active() ) { ImGui::NewLine(); TextColoredUnformatted( ImVec4( 0xCC / 255.f, 0xCC / 255.f, 0x22 / 255.f, 1.f ), m_worker.GetString( ev.text ) ); diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 2e8570a8..9cc10440 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -911,10 +911,10 @@ Worker::Worker( FileRead& f, EventType::Type eventMask ) { ReadTimelinePre042( f, td->timeline, CompressThread( tid ), tsz, fileVer ); } - else if( fileVer <= FileVersion( 0, 5, 1 ) ) + else if( fileVer <= FileVersion( 0, 5, 7 ) ) { int64_t refTime = 0; - ReadTimelinePre052( f, td->timeline, CompressThread( tid ), tsz, refTime, fileVer ); + ReadTimelinePre058( f, td->timeline, CompressThread( tid ), tsz, refTime, fileVer ); } else { @@ -1298,7 +1298,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask ) } } - if( fileVer >= FileVersion( 0, 4, 6 ) ) + if( fileVer >= FileVersion( 0, 5, 8 ) ) { f.Read( sz ); m_data.callstackFrameMap.reserve( sz ); @@ -1316,20 +1316,54 @@ Worker::Worker( FileRead& f, EventType::Type eventMask ) m_data.callstackFrameMap.emplace( id, frameData ); } } + else if( fileVer >= FileVersion( 0, 4, 6 ) ) + { + f.Read( sz ); + m_data.callstackFrameMap.reserve( sz ); + for( uint64_t i=0; i(); + f.Read( frameData->size ); + + frameData->data = m_slab.AllocInit( frameData->size ); + for( uint8_t j=0; jsize; j++ ) + { + f.Read( str ); + if( str.active ) frameData->data[j].name.SetIdx( str.idx ); + f.Read( str ); + if( str.active ) frameData->data[j].file.SetIdx( str.idx ); + f.Read( frameData->data[j].line ); + } + + m_data.callstackFrameMap.emplace( id, frameData ); + } + } else if( fileVer >= FileVersion( 0, 4, 3 ) ) { f.Read( sz ); m_data.callstackFrameMap.reserve( sz ); for( uint64_t i=0; i(); f.Read( frameData->size ); - frameData->data = m_slab.Alloc( frameData->size ); - f.Read( frameData->data, sizeof( CallstackFrame ) * frameData->size ); + frameData->data = m_slab.AllocInit( frameData->size ); + for( uint8_t j=0; jsize; j++ ) + { + f.Read( str ); + if( str.active ) frameData->data[j].name.SetIdx( str.idx ); + f.Read( str ); + if( str.active ) frameData->data[j].file.SetIdx( str.idx ); + f.Read( frameData->data[j].line ); + } m_data.callstackFrameMap.emplace( PackPointer( ptr ), frameData ); } @@ -1340,14 +1374,19 @@ Worker::Worker( FileRead& f, EventType::Type eventMask ) m_data.callstackFrameMap.reserve( sz ); for( uint64_t i=0; i(); frameData->size = 1; - frameData->data = m_slab.Alloc(); - f.Read( frameData->data, sizeof( CallstackFrame ) ); + frameData->data = m_slab.AllocInit(); + f.Read( str ); + if( str.active ) frameData->data->name.SetIdx( str.idx ); + f.Read( str ); + if( str.active ) frameData->data->file.SetIdx( str.idx ); + f.Read( frameData->data->line ); m_data.callstackFrameMap.emplace( PackPointer( ptr ), frameData ); } @@ -1931,8 +1970,8 @@ const char* Worker::GetString( const StringRef& ref ) const const char* Worker::GetString( const StringIdx& idx ) const { - assert( idx.active ); - return m_data.stringData[idx.idx]; + assert( idx.Active() ); + return m_data.stringData[idx.Idx()]; } static const char* BadExternalThreadNames[] = { @@ -2030,7 +2069,7 @@ const char* Worker::GetZoneName( const ZoneEvent& ev ) const const char* Worker::GetZoneName( const ZoneEvent& ev, const SourceLocation& srcloc ) const { - if( ev.name.active ) + if( ev.name.Active() ) { return GetString( ev.name ); } @@ -4537,7 +4576,7 @@ void Worker::ReadTimelinePre042( FileRead& f, ZoneEvent* zone, uint16_t thread, } } -void Worker::ReadTimelinePre052( FileRead& f, ZoneEvent* zone, uint16_t thread, int64_t& refTime, int fileVer ) +void Worker::ReadTimelinePre058( FileRead& f, ZoneEvent* zone, uint16_t thread, int64_t& refTime, int fileVer ) { uint64_t sz; f.Read( sz ); @@ -4550,7 +4589,7 @@ void Worker::ReadTimelinePre052( FileRead& f, ZoneEvent* zone, uint16_t thread, zone->child = m_data.zoneChildren.size(); m_data.zoneChildren.push_back( Vector() ); Vector tmp; - ReadTimelinePre052( f, tmp, thread, sz, refTime, fileVer ); + ReadTimelinePre058( f, tmp, thread, sz, refTime, fileVer ); m_data.zoneChildren[zone->child] = std::move( tmp ); } } @@ -4645,7 +4684,7 @@ void Worker::ReadTimeline( FileRead& f, Vector& vec, uint16_t thread do { s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed ); - uint16_t srcloc; + int16_t srcloc; f.Read( srcloc ); zone->SetSrcLoc( srcloc ); // Use zone->end as scratch buffer for zone start time offset. @@ -4682,7 +4721,26 @@ void Worker::ReadTimelinePre042( FileRead& f, Vector& vec, uint16_t f.Read( srcloc ); zone->SetSrcLoc( srcloc ); f.Skip( 4 ); - f.Read( &zone->text, sizeof( zone->text ) + sizeof( zone->callstack ) + sizeof( zone->name ) ); + __StringIdxOld str; + f.Read( str ); + if( str.active ) + { + zone->text.SetIdx( str.idx ); + } + else + { + new ( &zone->text ) StringIdx(); + } + f.Read( zone->callstack ); + f.Read( str ); + if( str.active ) + { + zone->name.SetIdx( str.idx ); + } + else + { + new ( &zone->name ) StringIdx(); + } ReadTimelinePre042( f, zone, thread, fileVer ); #ifdef TRACY_NO_STATISTICS ReadTimelineUpdateStatistics( zone, thread ); @@ -4690,9 +4748,9 @@ void Worker::ReadTimelinePre042( FileRead& f, Vector& vec, uint16_t } } -void Worker::ReadTimelinePre052( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int64_t& refTime, int fileVer ) +void Worker::ReadTimelinePre058( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int64_t& refTime, int fileVer ) { - assert( fileVer <= FileVersion( 0, 5, 1 ) ); + assert( fileVer <= FileVersion( 0, 5, 7 ) ); assert( size != 0 ); vec.reserve_exact( size, m_slab ); m_data.zonesCnt += size; @@ -4706,23 +4764,51 @@ void Worker::ReadTimelinePre052( FileRead& f, Vector& vec, uint16_t do { s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed ); - // Use zone->end as scratch buffer for zone start time offset. - f.Read( &zone->end, sizeof( zone->end ) ); - int16_t srcloc; - f.Read( srcloc ); - zone->SetSrcLoc( srcloc ); - if( fileVer <= FileVersion( 0, 5, 0 ) ) + if( fileVer >= FileVersion( 0, 5, 2 ) ) { - f.Skip( 4 ); + int16_t srcloc; + f.Read( srcloc ); + zone->SetSrcLoc( srcloc ); + f.Read( &zone->end, sizeof( zone->end ) ); } else { - f.Skip( 2 ); + f.Read( &zone->end, sizeof( zone->end ) ); + int16_t srcloc; + f.Read( srcloc ); + zone->SetSrcLoc( srcloc ); + if( fileVer <= FileVersion( 0, 5, 0 ) ) + { + f.Skip( 4 ); + } + else + { + f.Skip( 2 ); + } + } + __StringIdxOld str; + f.Read( str ); + if( str.active ) + { + zone->text.SetIdx( str.idx ); + } + else + { + new ( &zone->text ) StringIdx(); + } + f.Read( zone->callstack ); + f.Read( str ); + if( str.active ) + { + zone->name.SetIdx( str.idx ); + } + else + { + new ( &zone->name ) StringIdx(); } - f.Read( &zone->text, sizeof( zone->text ) + sizeof( zone->callstack ) + sizeof( zone->name ) ); refTime += zone->end; zone->SetStart( refTime - m_data.baseTime ); - ReadTimelinePre052( f, zone, thread, refTime, fileVer ); + ReadTimelinePre058( f, zone, thread, refTime, fileVer ); zone->end = ReadTimeOffset( f, refTime ); if( zone->end >= 0 ) zone->end -= m_data.baseTime; #ifdef TRACY_NO_STATISTICS diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 3d51dc1c..36ccbfee 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -130,8 +130,8 @@ private: { const auto& v = data->data[i]; hash = ( ( hash << 5 ) + hash ) ^ size_t( v.line ); - hash = ( ( hash << 5 ) + hash ) ^ size_t( v.file.__data ); - hash = ( ( hash << 5 ) + hash ) ^ size_t( v.name.__data ); + hash = ( ( hash << 5 ) + hash ) ^ size_t( v.file.Idx() ); + hash = ( ( hash << 5 ) + hash ) ^ size_t( v.name.Idx() ); } return hash; } @@ -517,7 +517,7 @@ private: tracy_force_inline void ReadTimeline( FileRead& f, ZoneEvent* zone, uint16_t thread, int64_t& refTime ); tracy_force_inline void ReadTimelinePre042( FileRead& f, ZoneEvent* zone, uint16_t thread, int fileVer ); - tracy_force_inline void ReadTimelinePre052( FileRead& f, ZoneEvent* zone, uint16_t thread, int64_t& refTime, int fileVer ); + tracy_force_inline void ReadTimelinePre058( FileRead& f, ZoneEvent* zone, uint16_t thread, int64_t& refTime, int fileVer ); tracy_force_inline void ReadTimeline( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime ); tracy_force_inline void ReadTimelinePre052( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int fileVer ); @@ -525,7 +525,7 @@ private: void ReadTimeline( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int64_t& refTime ); void ReadTimelinePre042( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int fileVer ); - void ReadTimelinePre052( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int64_t& refTime, int fileVer ); + void ReadTimelinePre058( FileRead& f, Vector& vec, uint16_t thread, uint64_t size, int64_t& refTime, int fileVer ); void ReadTimeline( FileRead& f, Vector& vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime ); void ReadTimelinePre052( FileRead& f, Vector& vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime, int fileVer );