From 4f6e9bbb65d2af998619dfc15e9e4a3fe5932a37 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 13 Nov 2021 21:49:04 +0100 Subject: [PATCH] Generic callstack tree builder. Previously this was exclusive for memory callstacks. --- server/TracyEvent.hpp | 13 +++++ server/TracyView.cpp | 107 ++++++++++++++++++++++++++++++++++++++++-- server/TracyView.hpp | 3 ++ 3 files changed, 118 insertions(+), 5 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 4d1330b9..2763a2a2 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -471,6 +471,19 @@ struct MemCallstackFrameTree enum { MemCallstackFrameTreeSize = sizeof( MemCallstackFrameTree ) }; +struct CallstackFrameTree +{ + CallstackFrameTree( CallstackFrameId id ) : frame( id ), count( 0 ) {} + + CallstackFrameId frame; + uint32_t count; + unordered_flat_map children; + unordered_flat_set callstacks; +}; + +enum { CallstackFrameTreeSize = sizeof( CallstackFrameTree ) }; + + struct CrashEvent { uint64_t thread = 0; diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 6abddd0a..3801c55f 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -16756,17 +16756,19 @@ void View::ListMemData( std::vector& vec, std::function& tree, CallstackFrameId idx, const Worker& worker ) +template +static tracy_force_inline T* GetFrameTreeItemNoGroup( unordered_flat_map& tree, CallstackFrameId idx, const Worker& worker ) { auto it = tree.find( idx.data ); if( it == tree.end() ) { - it = tree.emplace( idx.data, MemCallstackFrameTree( idx ) ).first; + it = tree.emplace( idx.data, T( idx ) ).first; } return &it->second; } -static tracy_force_inline MemCallstackFrameTree* GetFrameTreeItemGroup( unordered_flat_map& tree, CallstackFrameId idx, const Worker& worker ) +template +static tracy_force_inline T* GetFrameTreeItemGroup( unordered_flat_map& tree, CallstackFrameId idx, const Worker& worker ) { auto frameDataPtr = worker.GetCallstackFrame( idx ); if( !frameDataPtr ) return nullptr; @@ -16778,7 +16780,7 @@ static tracy_force_inline MemCallstackFrameTree* GetFrameTreeItemGroup( unordere auto it = tree.find( fidx ); if( it == tree.end() ) { - it = tree.emplace( fidx, MemCallstackFrameTree( idx ) ).first; + it = tree.emplace( fidx, T( idx ) ).first; } return &it->second; } @@ -16881,10 +16883,57 @@ unordered_flat_map View::GetCallstackFrameTreeB } } } - return root; } +unordered_flat_map View::GetCallstackFrameTreeBottomUp( const unordered_flat_map& stacks, bool group ) const +{ + unordered_flat_map root; + if( group ) + { + for( auto& path : stacks ) + { + auto& cs = m_worker.GetCallstack( path.first ); + + auto base = cs.back(); + auto treePtr = GetFrameTreeItemGroup( root, base, m_worker ); + if( treePtr ) + { + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + for( int i = int( cs.size() ) - 2; i >= 0; i-- ) + { + treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker ); + if( !treePtr ) break; + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + } + } + } + } + else + { + for( auto& path : stacks ) + { + auto& cs = m_worker.GetCallstack( path.first ); + + auto base = cs.back(); + auto treePtr = GetFrameTreeItemNoGroup( root, base, m_worker ); + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + + for( int i = int( cs.size() ) - 2; i >= 0; i-- ) + { + treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i], m_worker ); + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + } + } + } + return root; +} + + unordered_flat_map View::GetCallstackFrameTreeTopDown( const MemData& mem ) const { unordered_flat_map root; @@ -16938,6 +16987,54 @@ unordered_flat_map View::GetCallstackFrameTreeT return root; } +unordered_flat_map View::GetCallstackFrameTreeTopDown( const unordered_flat_map& stacks, bool group ) const +{ + unordered_flat_map root; + if( group ) + { + for( auto& path : stacks ) + { + auto& cs = m_worker.GetCallstack( path.first ); + + auto base = cs.front(); + auto treePtr = GetFrameTreeItemGroup( root, base, m_worker ); + if( treePtr ) + { + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + + for( uint16_t i = 1; i < cs.size(); i++ ) + { + treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker ); + if( !treePtr ) break; + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + } + } + } + } + else + { + for( auto& path : stacks ) + { + auto& cs = m_worker.GetCallstack( path.first ); + + auto base = cs.front(); + auto treePtr = GetFrameTreeItemNoGroup( root, base, m_worker ); + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + + for( uint16_t i = 1; i < cs.size(); i++ ) + { + treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i], m_worker ); + treePtr->count += path.second; + treePtr->callstacks.emplace( path.first ); + } + } + } + return root; +} + enum { ChunkBits = 10 }; enum { PageBits = 10 }; diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 7cf98991..7f882f4f 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -232,6 +232,9 @@ private: void DrawFrameTreeLevel( const unordered_flat_map& tree, int& idx ); void DrawZoneList( int id, const Vector>& zones ); + unordered_flat_map GetCallstackFrameTreeBottomUp( const unordered_flat_map& stacks, bool group ) const; + unordered_flat_map GetCallstackFrameTreeTopDown( const unordered_flat_map& stacks, bool group ) const; + void DrawInfoWindow(); void DrawZoneInfoWindow(); void DrawGpuInfoWindow();