1
0
mirror of https://github.com/wolfpld/tracy.git synced 2025-03-20 07:40:02 +08:00

Greatly simplify call stack tree calculation.

Instead of caching paths, compute accumulated cost of each path and only
then create the tree, going through each path just once.
This commit is contained in:
Bartosz Taudul 2018-08-19 16:34:26 +02:00
parent e1821e439a
commit 6224daf9c9

View File

@ -6537,9 +6537,15 @@ static tracy_force_inline CallstackFrameTree* GetFrameTreeItem( std::vector<Call
std::vector<CallstackFrameTree> View::GetCallstackFrameTree( const MemData& mem ) const std::vector<CallstackFrameTree> View::GetCallstackFrameTree( const MemData& mem ) const
{ {
struct PathData
{
uint32_t cnt;
uint64_t mem;
};
std::vector<CallstackFrameTree> root; std::vector<CallstackFrameTree> root;
std::vector<Vector<uint32_t>> paths; flat_hash_map<uint32_t, PathData, nohash<uint32_t>> pathSum;
paths.resize( m_worker.GetCallstackPayloadCount() ); pathSum.reserve( m_worker.GetCallstackPayloadCount() );
const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2;
@ -6548,48 +6554,36 @@ std::vector<CallstackFrameTree> View::GetCallstackFrameTree( const MemData& mem
if( ev.csAlloc == 0 ) continue; if( ev.csAlloc == 0 ) continue;
if( m_memInfo.restrictTime && ev.timeAlloc >= zvMid ) continue; if( m_memInfo.restrictTime && ev.timeAlloc >= zvMid ) continue;
auto& path = paths[ev.csAlloc]; auto it = pathSum.find( ev.csAlloc );
if( !path.empty() ) if( it == pathSum.end() )
{ {
auto treePtr = &root; pathSum.emplace( ev.csAlloc, PathData { 1, ev.size } );
CallstackFrameTree* node = nullptr;
for( auto& v : path )
{
node = treePtr->data() + v;
node->countInclusive++;
node->allocInclusive += ev.size;
treePtr = &node->children;
}
assert( treePtr->empty() );
node->countExclusive++;
node->allocExclusive += ev.size;
} }
else else
{ {
auto& cs = m_worker.GetCallstack( ev.csAlloc ); it->second.cnt++;
Vector<uint32_t> path; it->second.mem += ev.size;
path.reserve( cs.size() ); }
}
for( auto& path : pathSum )
{
auto& cs = m_worker.GetCallstack( path.first );
auto base = cs.back(); auto base = cs.back();
auto treePtr = GetFrameTreeItem( root, base ); auto treePtr = GetFrameTreeItem( root, base );
treePtr->countInclusive++; treePtr->countInclusive += path.second.cnt;
treePtr->allocInclusive += ev.size; treePtr->allocInclusive += path.second.mem;
path.push_back( uint32_t( treePtr - root.data() ) );
for( int i = int( cs.size() ) - 2; i >= 0; i-- ) for( int i = int( cs.size() ) - 2; i >= 0; i-- )
{ {
auto newTreePtr = GetFrameTreeItem( treePtr->children, cs[i] ); treePtr = GetFrameTreeItem( treePtr->children, cs[i] );
newTreePtr->countInclusive++; treePtr->countInclusive += path.second.cnt;
newTreePtr->allocInclusive += ev.size; treePtr->allocInclusive += path.second.mem;
path.push_back( uint32_t( newTreePtr - treePtr->children.data() ) );
treePtr = newTreePtr;
} }
treePtr->countExclusive++; treePtr->countExclusive += path.second.cnt;
treePtr->allocExclusive += ev.size; treePtr->allocExclusive += path.second.mem;
paths[ev.csAlloc] = std::move( path );
}
} }
return root; return root;
} }