diff --git a/profiler/src/profiler/TracyView.cpp b/profiler/src/profiler/TracyView.cpp index 7a165d3d..cec5cac8 100644 --- a/profiler/src/profiler/TracyView.cpp +++ b/profiler/src/profiler/TracyView.cpp @@ -56,6 +56,11 @@ View::View( void(*cbMainThread)(const std::function&, bool), const char* , m_cbMainThread( cbMainThread ) , m_achievementsMgr( amgr ) , m_achievements( config.achievements ) +#ifdef __EMSCRIPTEN__ + , m_td( 2, "ViewMt" ) +#else + , m_td( std::thread::hardware_concurrency(), "ViewMt" ) +#endif { InitTextEditor(); SetupConfig( config ); @@ -80,6 +85,11 @@ View::View( void(*cbMainThread)(const std::function&, bool), FileRead& f , m_cbMainThread( cbMainThread ) , m_achievementsMgr( amgr ) , m_achievements( config.achievements ) +#ifdef __EMSCRIPTEN__ + , m_td( 2, "ViewMt" ) +#else + , m_td( std::thread::hardware_concurrency(), "ViewMt" ) +#endif { m_notificationTime = 4; m_notificationText = std::string( "Trace loaded in " ) + TimeToString( m_worker.GetLoadTime() ); diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index 6697e74a..66e137ba 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -22,6 +22,7 @@ #include "TracyUtility.hpp" #include "TracyViewData.hpp" #include "../server/TracyFileWrite.hpp" +#include "../server/TracyTaskDispatch.hpp" #include "../server/TracyShortPtr.hpp" #include "../server/TracyWorker.hpp" #include "../server/tracy_robin_hood.h" @@ -277,9 +278,9 @@ private: void DrawFlameGraph(); void DrawFlameGraphHeader( uint64_t timespan ); void DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, uint64_t ts, int depth, bool samples ); - void BuildFlameGraph( const Worker& worker, Vector& data, const Vector>& zones ); - void BuildFlameGraph( const Worker& worker, Vector& data, const Vector>& zones, const ContextSwitch* ctx ); - void BuildFlameGraph( const Worker& worker, Vector& data, const Vector& samples ); + void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones ); + void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones, const ContextSwitch* ctx ); + void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples ); void ListMemData( std::vector& vec, const std::function& DrawAddress, int64_t startTime = -1, uint64_t pool = 0 ); @@ -899,6 +900,8 @@ private: AchievementsMgr* m_achievementsMgr; bool m_achievements = false; + + TaskDispatch m_td; }; } diff --git a/profiler/src/profiler/TracyView_FlameGraph.cpp b/profiler/src/profiler/TracyView_FlameGraph.cpp index 7978c54f..f25d0c46 100644 --- a/profiler/src/profiler/TracyView_FlameGraph.cpp +++ b/profiler/src/profiler/TracyView_FlameGraph.cpp @@ -17,12 +17,12 @@ struct FlameGraphItem { int64_t srcloc; int64_t time; - Vector children; + std::vector children; }; -void View::BuildFlameGraph( const Worker& worker, Vector& data, const Vector>& zones ) +void View::BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones ) { - FlameGraphItem* it; + FlameGraphItem* cache; int16_t last = 0; if( zones.is_magic() ) @@ -35,25 +35,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, const auto duration = v.End() - v.Start(); if( srcloc == last ) { - it->time += duration; + cache->time += duration; if( v.HasChildren() ) { auto& children = worker.GetZoneChildren( v.Child() ); - BuildFlameGraph( worker, it->children, children ); + BuildFlameGraph( worker, cache->children, children ); } } else { - it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); + auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); if( it == data.end() ) { - data.push_back( FlameGraphItem { srcloc, duration } ); + data.emplace_back( FlameGraphItem { srcloc, duration } ); if( v.HasChildren() ) { auto& children = worker.GetZoneChildren( v.Child() ); BuildFlameGraph( worker, data.back().children, children ); } - it = &data.back(); + cache = &data.back(); } else { @@ -63,6 +63,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, auto& children = worker.GetZoneChildren( v.Child() ); BuildFlameGraph( worker, it->children, children ); } + cache = &*it; } last = srcloc; } @@ -77,25 +78,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, const auto duration = v->End() - v->Start(); if( srcloc == last ) { - it->time += duration; + cache->time += duration; if( v->HasChildren() ) { auto& children = worker.GetZoneChildren( v->Child() ); - BuildFlameGraph( worker, it->children, children ); + BuildFlameGraph( worker, cache->children, children ); } } else { - it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); + auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); if( it == data.end() ) { - data.push_back( FlameGraphItem { srcloc, duration } ); + data.emplace_back( FlameGraphItem { srcloc, duration } ); if( v->HasChildren() ) { auto& children = worker.GetZoneChildren( v->Child() ); BuildFlameGraph( worker, data.back().children, children ); } - it = &data.back(); + cache = &data.back(); } else { @@ -105,6 +106,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, auto& children = worker.GetZoneChildren( v->Child() ); BuildFlameGraph( worker, it->children, children ); } + cache = &*it; } last = srcloc; } @@ -112,10 +114,10 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, } } -void View::BuildFlameGraph( const Worker& worker, Vector& data, const Vector>& zones, const ContextSwitch* ctx ) +void View::BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones, const ContextSwitch* ctx ) { assert( ctx ); - FlameGraphItem* it; + FlameGraphItem* cache; int16_t last = 0; if( zones.is_magic() ) @@ -130,25 +132,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break; if( srcloc == last ) { - it->time += duration; + cache->time += duration; if( v.HasChildren() ) { auto& children = worker.GetZoneChildren( v.Child() ); - BuildFlameGraph( worker, it->children, children, ctx ); + BuildFlameGraph( worker, cache->children, children, ctx ); } } else { - it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); + auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); if( it == data.end() ) { - data.push_back( FlameGraphItem { srcloc, duration } ); + data.emplace_back( FlameGraphItem { srcloc, duration } ); if( v.HasChildren() ) { auto& children = worker.GetZoneChildren( v.Child() ); BuildFlameGraph( worker, data.back().children, children, ctx ); } - it = &data.back(); + cache = &data.back(); } else { @@ -158,6 +160,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, auto& children = worker.GetZoneChildren( v.Child() ); BuildFlameGraph( worker, it->children, children, ctx ); } + cache = &*it; } last = srcloc; } @@ -174,25 +177,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break; if( srcloc == last ) { - it->time += duration; + cache->time += duration; if( v->HasChildren() ) { auto& children = worker.GetZoneChildren( v->Child() ); - BuildFlameGraph( worker, it->children, children, ctx ); + BuildFlameGraph( worker, cache->children, children, ctx ); } } else { - it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); + auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } ); if( it == data.end() ) { - data.push_back( FlameGraphItem { srcloc, duration } ); + data.emplace_back( FlameGraphItem { srcloc, duration } ); if( v->HasChildren() ) { auto& children = worker.GetZoneChildren( v->Child() ); BuildFlameGraph( worker, data.back().children, children, ctx ); } - it = &data.back(); + cache = &data.back(); } else { @@ -202,6 +205,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, auto& children = worker.GetZoneChildren( v->Child() ); BuildFlameGraph( worker, it->children, children, ctx ); } + cache = &*it; } last = srcloc; } @@ -209,7 +213,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, } } -void View::BuildFlameGraph( const Worker& worker, Vector& data, const Vector& samples ) +void View::BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples ) { for( auto& v : samples ) { @@ -232,7 +236,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, auto it = std::find_if( vec->begin(), vec->end(), [symaddr]( const auto& v ) { return v.srcloc == symaddr; } ); if( it == vec->end() ) { - vec->push_back( FlameGraphItem { (int64_t)symaddr, 1 } ); + vec->emplace_back( FlameGraphItem { (int64_t)symaddr, 1 } ); vec = &vec->back().children; } else @@ -247,21 +251,12 @@ void View::BuildFlameGraph( const Worker& worker, Vector& data, } } -static void SortFlameGraph( Vector& data ) +static void SortFlameGraph( std::vector& data ) { pdqsort_branchless( data.begin(), data.end(), []( const FlameGraphItem& lhs, const FlameGraphItem& rhs ) { return lhs.time > rhs.time; } ); for( auto& v : data ) SortFlameGraph( v.children ); } -static void FreeVector( Vector& data ) -{ - for( auto& v : data ) - { - FreeVector( v.children ); - v.children.~Vector(); - } -} - struct FlameGraphContext { ImDrawList* draw; @@ -521,6 +516,23 @@ void View::DrawFlameGraphHeader( uint64_t timespan ) } } +static void MergeFlameGraph( std::vector& dst, std::vector&& src ) +{ + for( auto& v : src ) + { + auto it = std::find_if( dst.begin(), dst.end(), [&v]( const auto& vv ) { return vv.srcloc == v.srcloc; } ); + if( it == dst.end() ) + { + dst.emplace_back( std::move( v ) ); + } + else + { + it->time += v.time; + MergeFlameGraph( it->children, std::move( v.children ) ); + } + } +} + void View::DrawFlameGraph() { const auto scale = GetScale(); @@ -613,8 +625,13 @@ void View::DrawFlameGraph() ImGui::Separator(); ImGui::PopStyleVar(); - Vector data; + size_t sz = 0; + for( auto& thread : m_threadOrder ) if( FlameGraphThread( thread->id ) ) sz++; + std::vector> threadData; + threadData.resize( sz ); + + size_t idx = 0; if( m_flameMode == 0 ) { for( auto& thread : m_worker.GetThreadData() ) @@ -624,12 +641,20 @@ void View::DrawFlameGraph() if( m_flameRunningTime ) { const auto ctx = m_worker.GetContextSwitchData( thread->id ); - if( ctx ) BuildFlameGraph( m_worker, data, thread->timeline, ctx ); + if( ctx ) + { + m_td.Queue( [this, idx, ctx, thread, &threadData] { + BuildFlameGraph( m_worker, threadData[idx], thread->timeline, ctx ); + } ); + } } else { - BuildFlameGraph( m_worker, data, thread->timeline ); + m_td.Queue( [this, idx, thread, &threadData] { + BuildFlameGraph( m_worker, threadData[idx], thread->timeline ); + } ); } + idx++; } } } @@ -637,7 +662,24 @@ void View::DrawFlameGraph() { for( auto& thread : m_worker.GetThreadData() ) { - if( FlameGraphThread( thread->id ) ) BuildFlameGraph( m_worker, data, thread->samples ); + if( FlameGraphThread( thread->id ) ) + { + m_td.Queue( [this, idx, thread, &threadData] { + BuildFlameGraph( m_worker, threadData[idx], thread->samples ); + } ); + idx++; + } + } + } + m_td.Sync(); + + std::vector data; + if( !threadData.empty() ) + { + std::swap( data, threadData[0] ); + for( size_t i=1; i