Generic callstack tree builder.

Previously this was exclusive for memory callstacks.
This commit is contained in:
Bartosz Taudul 2021-11-13 21:49:04 +01:00
parent c6be16dcd2
commit 4f6e9bbb65
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
3 changed files with 118 additions and 5 deletions

View File

@ -471,6 +471,19 @@ struct MemCallstackFrameTree
enum { MemCallstackFrameTreeSize = sizeof( MemCallstackFrameTree ) }; enum { MemCallstackFrameTreeSize = sizeof( MemCallstackFrameTree ) };
struct CallstackFrameTree
{
CallstackFrameTree( CallstackFrameId id ) : frame( id ), count( 0 ) {}
CallstackFrameId frame;
uint32_t count;
unordered_flat_map<uint64_t, CallstackFrameTree> children;
unordered_flat_set<uint32_t> callstacks;
};
enum { CallstackFrameTreeSize = sizeof( CallstackFrameTree ) };
struct CrashEvent struct CrashEvent
{ {
uint64_t thread = 0; uint64_t thread = 0;

View File

@ -16756,17 +16756,19 @@ void View::ListMemData( std::vector<const MemEvent*>& vec, std::function<void(co
} }
} }
static tracy_force_inline MemCallstackFrameTree* GetFrameTreeItemNoGroup( unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, CallstackFrameId idx, const Worker& worker ) template<class T>
static tracy_force_inline T* GetFrameTreeItemNoGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )
{ {
auto it = tree.find( idx.data ); auto it = tree.find( idx.data );
if( it == tree.end() ) if( it == tree.end() )
{ {
it = tree.emplace( idx.data, MemCallstackFrameTree( idx ) ).first; it = tree.emplace( idx.data, T( idx ) ).first;
} }
return &it->second; return &it->second;
} }
static tracy_force_inline MemCallstackFrameTree* GetFrameTreeItemGroup( unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, CallstackFrameId idx, const Worker& worker ) template<class T>
static tracy_force_inline T* GetFrameTreeItemGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )
{ {
auto frameDataPtr = worker.GetCallstackFrame( idx ); auto frameDataPtr = worker.GetCallstackFrame( idx );
if( !frameDataPtr ) return nullptr; if( !frameDataPtr ) return nullptr;
@ -16778,7 +16780,7 @@ static tracy_force_inline MemCallstackFrameTree* GetFrameTreeItemGroup( unordere
auto it = tree.find( fidx ); auto it = tree.find( fidx );
if( it == tree.end() ) if( it == tree.end() )
{ {
it = tree.emplace( fidx, MemCallstackFrameTree( idx ) ).first; it = tree.emplace( fidx, T( idx ) ).first;
} }
return &it->second; return &it->second;
} }
@ -16881,10 +16883,57 @@ unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeB
} }
} }
} }
return root; return root;
} }
unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const
{
unordered_flat_map<uint64_t, CallstackFrameTree> 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<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeTopDown( const MemData& mem ) const unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeTopDown( const MemData& mem ) const
{ {
unordered_flat_map<uint64_t, MemCallstackFrameTree> root; unordered_flat_map<uint64_t, MemCallstackFrameTree> root;
@ -16938,6 +16987,54 @@ unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeT
return root; return root;
} }
unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const
{
unordered_flat_map<uint64_t, CallstackFrameTree> 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 { ChunkBits = 10 };
enum { PageBits = 10 }; enum { PageBits = 10 };

View File

@ -232,6 +232,9 @@ private:
void DrawFrameTreeLevel( const unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, int& idx ); void DrawFrameTreeLevel( const unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, int& idx );
void DrawZoneList( int id, const Vector<short_ptr<ZoneEvent>>& zones ); void DrawZoneList( int id, const Vector<short_ptr<ZoneEvent>>& zones );
unordered_flat_map<uint64_t, CallstackFrameTree> GetCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const;
unordered_flat_map<uint64_t, CallstackFrameTree> GetCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const;
void DrawInfoWindow(); void DrawInfoWindow();
void DrawZoneInfoWindow(); void DrawZoneInfoWindow();
void DrawGpuInfoWindow(); void DrawGpuInfoWindow();