diff --git a/profiler/src/profiler/TracyDisassembly.cpp b/profiler/src/profiler/TracyDisassembly.cpp index c35b4b8f..aba7d3ce 100644 --- a/profiler/src/profiler/TracyDisassembly.cpp +++ b/profiler/src/profiler/TracyDisassembly.cpp @@ -863,7 +863,7 @@ void GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, b } } -void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ) +void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ) { if( !worker.AreSymbolSamplesReady() ) return; auto sym = worker.GetSymbolData( baseAddr ); diff --git a/profiler/src/profiler/TracyDisassembly.hpp b/profiler/src/profiler/TracyDisassembly.hpp index 58eea6ad..e074d770 100644 --- a/profiler/src/profiler/TracyDisassembly.hpp +++ b/profiler/src/profiler/TracyDisassembly.hpp @@ -138,7 +138,7 @@ std::string FormatDisassemblyLine( const AsmLine& opcode, Worker& worker, std::v nlohmann::json JsonDisassembly( uint64_t symAddr, Worker& worker, const View& view ); void GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ); -void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ); +void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ); } diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 2bc39ce3..bbb26d63 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -685,6 +685,8 @@ struct ChildSample uint64_t addr; }; +struct ChildSampleSort { bool operator()( const ChildSample& lhs, const ChildSample& rhs ) const { return lhs.time.Val() < rhs.time.Val(); }; }; + struct SectionItem { diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index c34af597..bc02f41a 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1957,11 +1957,11 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allow auto it = m_data.childSamples.find( addr ); if( it == m_data.childSamples.end() ) { - m_data.childSamples.emplace( addr, Vector( ChildSample { time, childAddr } ) ); + m_data.childSamples.emplace( addr, SortedVector( ChildSample { time, childAddr } ) ); } else { - it->second.push_back_non_empty( ChildSample { time, childAddr } ); + it->second.push_back( ChildSample { time, childAddr } ); } childAddr = addr; } @@ -1973,7 +1973,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allow } for( auto& v : m_data.childSamples ) { - pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } ); + v.second.ensure_sorted(); } std::lock_guard lock( m_data.lock ); m_data.symbolSamplesReady = true; @@ -2321,11 +2321,15 @@ const Vector* Worker::GetSamplesForSymbol( uint64_t symAddr ) c return &it->second; } -const Vector* Worker::GetChildSamples( uint64_t addr ) const +const SortedVector* Worker::GetChildSamples( uint64_t addr ) { assert( m_data.symbolSamplesReady ); auto it = m_data.childSamples.find( addr ); if( it == m_data.childSamples.end() ) return nullptr; + // Out-of-order insertions may happen during live capture, e.g. when samples postponed + // due to missing context switch data are finally processed. Sorting is done lazily, as + // the vectors are only ever read here. + it->second.ensure_sorted(); return &it->second; } #endif @@ -6674,11 +6678,11 @@ void Worker::ProcessCallstackSampleImplStats( const SampleData& sd, ThreadData& auto it = m_data.childSamples.find( addr ); if( it == m_data.childSamples.end() ) { - m_data.childSamples.emplace( addr, Vector( ChildSample { sd.time, childAddr } ) ); + m_data.childSamples.emplace( addr, SortedVector( ChildSample { sd.time, childAddr } ) ); } else { - it->second.push_back_non_empty( ChildSample { sd.time, childAddr } ); + it->second.push_back( ChildSample { sd.time, childAddr } ); } childAddr = addr; } diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 3de937a3..22cd9410 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -342,7 +342,7 @@ private: unordered_flat_map> instructionPointersMap; unordered_flat_map> symbolSamples; unordered_flat_map, CallstackFrameIdHash, CallstackFrameIdCompare> pendingSymbolSamples; - unordered_flat_map> childSamples; + unordered_flat_map> childSamples; bool newFramesWereReceived = false; bool callstackSamplesReady = false; bool newContextSwitchesReceived = false; @@ -598,7 +598,7 @@ public: const VarArray& GetSyntheticCallstack( uint32_t idx ) const { return *m_data.syntheticCallstackPayload[idx]; } const CallstackFrameData* GetSyntheticCallstackFrame( const CallstackFrameId& ptr ) const; const Vector* GetSamplesForSymbol( uint64_t symAddr ) const; - const Vector* GetChildSamples( uint64_t addr ) const; + const SortedVector* GetChildSamples( uint64_t addr ); #endif const CrashEvent& GetCrashEvent() const { return m_data.crashEvent; }