diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 63b74f86..332629d2 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -212,6 +212,25 @@ struct ZoneExtra enum { ZoneExtraSize = sizeof( ZoneExtra ) }; +// This union exploits the fact that the current implementations of x64 and arm64 do not provide +// full 64 bit address space. The high bits must be bit-extended, so 0x80... is an invalid pointer. +// This allows using the highest bit as a selector between a native pointer and a table index here. +union CallstackFrameId +{ + struct + { + uint64_t idx : 62; + uint64_t sel : 1; + uint64_t custom : 1; + }; + uint64_t data; +}; + +enum { CallstackFrameIdSize = sizeof( CallstackFrameId ) }; + +static tracy_force_inline bool operator==( const CallstackFrameId& lhs, const CallstackFrameId& rhs ) { return lhs.data == rhs.data; } + + struct SampleData { Int48 time; @@ -221,6 +240,15 @@ struct SampleData enum { SampleDataSize = sizeof( SampleData ) }; +struct SampleDataRange +{ + Int48 time; + CallstackFrameId ip; +}; + +enum { SampleDataRangeSize = sizeof( SampleDataRange ) }; + + struct LockEvent { enum class Type : uint8_t @@ -368,24 +396,6 @@ struct CallstackFrameData enum { CallstackFrameDataSize = sizeof( CallstackFrameData ) }; -// This union exploits the fact that the current implementations of x64 and arm64 do not provide -// full 64 bit address space. The high bits must be bit-extended, so 0x80... is an invalid pointer. -// This allows using the highest bit as a selector between a native pointer and a table index here. -union CallstackFrameId -{ - struct - { - uint64_t idx : 62; - uint64_t sel : 1; - uint64_t custom : 1; - }; - uint64_t data; -}; - -enum { CallstackFrameIdSize = sizeof( CallstackFrameId ) }; - -static tracy_force_inline bool operator==( const CallstackFrameId& lhs, const CallstackFrameId& rhs ) { return lhs.data == rhs.data; } - struct CallstackFrameTree { diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 8c92ed43..f9611273 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12048,10 +12048,10 @@ void View::DrawStatistics() auto samples = m_worker.GetSamplesForSymbol( v.first ); if( samples ) { - auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); if( it != samples->end() ) { - auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); const auto count = uint32_t( end - it ); data.push_back_no_space_check( SymList { v.first, 0, count } ); } @@ -12089,10 +12089,10 @@ void View::DrawStatistics() auto samples = m_worker.GetSamplesForSymbol( v.first ); if( samples ) { - auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); if( it != samples->end() ) { - auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); const auto count = uint32_t( end - it ); data.push_back_no_space_check( SymList { v.first, 0, count } ); } @@ -12146,10 +12146,10 @@ void View::DrawStatistics() auto samples = m_worker.GetSamplesForSymbol( v.first ); if( samples ) { - auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); if( it != samples->end() ) { - auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); const auto count = uint32_t( end - it ); data.push_back_no_space_check( SymList { v.first, 0, count } ); } @@ -12172,10 +12172,10 @@ void View::DrawStatistics() auto samples = m_worker.GetSamplesForSymbol( v.first ); if( samples ) { - auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); if( it != samples->end() ) { - auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } ); + auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } ); const auto count = uint32_t( end - it ); data.push_back_no_space_check( SymList { v.first, 0, count } ); } diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 26b5eeca..8becf68b 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1687,18 +1687,18 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) auto it = m_data.symbolSamples.find( symAddr ); if( it == m_data.symbolSamples.end() ) { - m_data.symbolSamples.emplace( symAddr, Vector( time ) ); + m_data.symbolSamples.emplace( symAddr, Vector( SampleDataRange { time, ip } ) ); } else { - it->second.push_back_non_empty( time ); + it->second.push_back_non_empty( SampleDataRange { time, ip } ); } } } } for( auto& v : m_data.symbolSamples ) { - pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs.Val(); } ); + pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } ); } std::lock_guard lock( m_data.lock ); m_data.symbolSamplesReady = true; @@ -2058,7 +2058,7 @@ const CallstackFrameData* Worker::GetParentCallstackFrame( const CallstackFrameI } } -const Vector* Worker::GetSamplesForSymbol( uint64_t symAddr ) const +const Vector* Worker::GetSamplesForSymbol( uint64_t symAddr ) const { assert( m_data.symbolSamplesReady ); auto it = m_data.symbolSamples.find( symAddr ); @@ -5383,18 +5383,18 @@ void Worker::ProcessCallstackSample( const QueueCallstackSample& ev ) auto sit = m_data.symbolSamples.find( symAddr ); if( sit == m_data.symbolSamples.end() ) { - m_data.symbolSamples.emplace( symAddr, Vector( sd.time ) ); + m_data.symbolSamples.emplace( symAddr, Vector( SampleDataRange { sd.time, ip } ) ); } else { - if( sit->second.back().Val() <= sd.time.Val() ) + if( sit->second.back().time.Val() <= sd.time.Val() ) { - sit->second.push_back_non_empty( sd.time ); + sit->second.push_back_non_empty( SampleDataRange { sd.time, ip } ); } else { - auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), sd.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.Val(); } ); - sit->second.insert( iit, sd.time ); + auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), sd.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.time.Val(); } ); + sit->second.insert( iit, SampleDataRange { sd.time, ip } ); } } } @@ -5412,11 +5412,11 @@ void Worker::ProcessCallstackSample( const QueueCallstackSample& ev ) auto sit = m_data.pendingSymbolSamples.find( ip ); if( sit == m_data.pendingSymbolSamples.end() ) { - m_data.pendingSymbolSamples.emplace( ip, Vector( sd.time ) ); + m_data.pendingSymbolSamples.emplace( ip, Vector( SampleDataRange { sd.time, ip } ) ); } else { - sit->second.push_back_non_empty( sd.time ); + sit->second.push_back_non_empty( SampleDataRange { sd.time, ip } ); } } } @@ -5517,20 +5517,20 @@ void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev ) auto sit = m_data.symbolSamples.find( ev.symAddr ); if( sit == m_data.symbolSamples.end() ) { - pdqsort_branchless( pit->second.begin(), pit->second.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs.Val(); } ); + pdqsort_branchless( pit->second.begin(), pit->second.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } ); m_data.symbolSamples.emplace( ev.symAddr, std::move( pit->second ) ); } else { for( auto& v : pit->second ) { - if( sit->second.back().Val() <= v.Val() ) + if( sit->second.back().time.Val() <= v.time.Val() ) { sit->second.push_back_non_empty( v ); } else { - auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), v.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.Val(); } ); + auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), v.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.time.Val(); } ); sit->second.insert( iit, v ); } } diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index a2c1480e..8d275fef 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -288,8 +288,8 @@ private: unordered_flat_map postponedSamples; unordered_flat_map pendingInstructionPointers; unordered_flat_map> instructionPointersMap; - unordered_flat_map> symbolSamples; - unordered_flat_map, CallstackFrameIdHash, CallstackFrameIdCompare> pendingSymbolSamples; + unordered_flat_map> symbolSamples; + unordered_flat_map, CallstackFrameIdHash, CallstackFrameIdCompare> pendingSymbolSamples; bool newFramesWereReceived = false; bool callstackSamplesReady = false; bool ghostZonesReady = false; @@ -503,7 +503,7 @@ public: #ifndef TRACY_NO_STATISTICS const VarArray& GetParentCallstack( uint32_t idx ) const { return *m_data.parentCallstackPayload[idx]; } const CallstackFrameData* GetParentCallstackFrame( const CallstackFrameId& ptr ) const; - const Vector* GetSamplesForSymbol( uint64_t symAddr ) const; + const Vector* GetSamplesForSymbol( uint64_t symAddr ) const; #endif const CrashEvent& GetCrashEvent() const { return m_data.crashEvent; }