1
0
mirror of https://github.com/wolfpld/tracy synced 2025-04-30 20:53:52 +00:00

Add bottom/top tree to callstack parents.

This commit is contained in:
Bartosz Taudul 2021-12-31 15:01:06 +01:00
parent 5d439c0165
commit 563daed10f
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
2 changed files with 445 additions and 175 deletions

View File

@ -16215,6 +16215,22 @@ void View::DrawSampleParents()
ImGui::SameLine();
TextDisabledUnformatted( m_worker.GetString( symbol->imageName ) );
ImGui::Separator();
ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );
if( ImGui::RadioButton( ICON_FA_TABLE " List", m_sampleParents.mode == 0 ) ) m_sampleParents.mode = 0;
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( ImGui::RadioButton( ICON_FA_TREE " Bottom-up tree", m_sampleParents.mode == 1 ) ) m_sampleParents.mode = 1;
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( ImGui::RadioButton( ICON_FA_TREE " Top-down tree", m_sampleParents.mode == 2 ) ) m_sampleParents.mode = 2;
ImGui::PopStyleVar();
ImGui::Separator();
switch( m_sampleParents.mode )
{
case 0:
{
TextDisabledUnformatted( "Entry call stack:" );
ImGui::SameLine();
if( ImGui::SmallButton( " " ICON_FA_CARET_LEFT " " ) )
@ -16445,6 +16461,43 @@ void View::DrawSampleParents()
}
ImGui::EndTable();
}
break;
}
case 1:
{
SmallCheckbox( "Group by function name", &m_sampleParents.groupBottomUp );
auto tree = GetParentsCallstackFrameTreeBottomUp( stats, m_sampleParents.groupBottomUp );
if( !tree.empty() )
{
int idx = 0;
DrawParentsFrameTreeLevel( tree, idx );
}
else
{
TextDisabledUnformatted( "No call stacks to show" );
}
break;
}
case 2:
{
SmallCheckbox( "Group by function name", &m_sampleParents.groupTopDown );
auto tree = GetParentsCallstackFrameTreeTopDown( stats, m_sampleParents.groupTopDown );
if( !tree.empty() )
{
int idx = 0;
DrawParentsFrameTreeLevel( tree, idx );
}
else
{
TextDisabledUnformatted( "No call stacks to show" );
}
break;
}
default:
assert( false );
break;
}
}
ImGui::End();
@ -17047,6 +17100,25 @@ static tracy_force_inline T* GetFrameTreeItemGroup( unordered_flat_map<uint64_t,
return &it->second;
}
template<class T>
static tracy_force_inline T* GetParentFrameTreeItemGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )
{
auto frameDataPtr = idx.custom ? worker.GetParentCallstackFrame( idx ) : worker.GetCallstackFrame( idx );
if( !frameDataPtr ) return nullptr;
auto& frameData = *frameDataPtr;
auto& frame = frameData.data[frameData.size-1];
auto fidx = frame.name.Idx();
auto it = tree.find( fidx );
if( it == tree.end() )
{
it = tree.emplace( fidx, T( idx ) ).first;
}
return &it->second;
}
unordered_flat_map<uint32_t, View::MemPathData> View::GetCallstackPaths( const MemData& mem, bool onlyActive ) const
{
unordered_flat_map<uint32_t, MemPathData> pathSum;
@ -17228,6 +17300,46 @@ unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeBott
return root;
}
unordered_flat_map<uint64_t, CallstackFrameTree> View::GetParentsCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const
{
unordered_flat_map<uint64_t, CallstackFrameTree> root;
if( group )
{
for( auto& path : stacks )
{
auto& cs = m_worker.GetParentCallstack( path.first );
auto base = cs.back();
auto treePtr = GetParentFrameTreeItemGroup( root, base, m_worker );
if( treePtr )
{
treePtr->count += path.second;
for( int i = int( cs.size() ) - 2; i >= 0; i-- )
{
treePtr = GetParentFrameTreeItemGroup( treePtr->children, cs[i], m_worker );
if( !treePtr ) break;
treePtr->count += path.second;
}
}
}
}
else
{
for( auto& path : stacks )
{
auto& cs = m_worker.GetParentCallstack( path.first );
auto base = cs.back();
auto treePtr = GetFrameTreeItemNoGroup( root, base, m_worker );
treePtr->count += path.second;
for( int i = int( cs.size() ) - 2; i >= 0; i-- )
{
treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i], m_worker );
treePtr->count += path.second;
}
}
}
return root;
}
unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeTopDown( const MemData& mem ) const
{
@ -17318,6 +17430,46 @@ unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeTopD
return root;
}
unordered_flat_map<uint64_t, CallstackFrameTree> View::GetParentsCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const
{
unordered_flat_map<uint64_t, CallstackFrameTree> root;
if( group )
{
for( auto& path : stacks )
{
auto& cs = m_worker.GetParentCallstack( path.first );
auto base = cs.front();
auto treePtr = GetParentFrameTreeItemGroup( root, base, m_worker );
if( treePtr )
{
treePtr->count += path.second;
for( uint16_t i = 1; i < cs.size(); i++ )
{
treePtr = GetParentFrameTreeItemGroup( treePtr->children, cs[i], m_worker );
if( !treePtr ) break;
treePtr->count += path.second;
}
}
}
}
else
{
for( auto& path : stacks )
{
auto& cs = m_worker.GetParentCallstack( path.first );
auto base = cs.front();
auto treePtr = GetFrameTreeItemNoGroup( root, base, m_worker );
treePtr->count += path.second;
for( uint16_t i = 1; i < cs.size(); i++ )
{
treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i], m_worker );
treePtr->count += path.second;
}
}
}
return root;
}
enum { ChunkBits = 10 };
enum { PageBits = 10 };
@ -18052,6 +18204,117 @@ void View::DrawFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrame
}
}
void View::DrawParentsFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx )
{
auto& io = ImGui::GetIO();
std::vector<unordered_flat_map<uint64_t, CallstackFrameTree>::const_iterator> sorted;
sorted.reserve( tree.size() );
for( auto it = tree.begin(); it != tree.end(); ++it )
{
sorted.emplace_back( it );
}
pdqsort_branchless( sorted.begin(), sorted.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs->second.count > rhs->second.count; } );
int lidx = 0;
for( auto& _v : sorted )
{
auto& v = _v->second;
const auto isKernel = ( m_worker.GetCanonicalPointer( v.frame ) >> 63 ) != 0;
idx++;
auto frameDataPtr = v.frame.custom ? m_worker.GetParentCallstackFrame( v.frame ) : m_worker.GetCallstackFrame( v.frame );
if( frameDataPtr )
{
auto& frameData = *frameDataPtr;
auto frame = frameData.data[frameData.size-1];
bool expand = false;
const auto frameName = m_worker.GetString( frame.name );
if( v.children.empty() )
{
ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );
if( frameName[0] == '[' )
{
TextDisabledUnformatted( frameName );
}
else if( isKernel )
{
TextColoredUnformatted( 0xFF8888FF, frameName );
}
else
{
ImGui::TextUnformatted( frameName );
}
ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );
}
else
{
ImGui::PushID( lidx++ );
if( frameName[0] == '[' ) ImGui::PushStyleColor( ImGuiCol_Text, 0x88FFFFFF );
else if( isKernel ) ImGui::PushStyleColor( ImGuiCol_Text, 0xFF8888FF );
if( tree.size() == 1 )
{
expand = ImGui::TreeNodeEx( frameName, ImGuiTreeNodeFlags_DefaultOpen );
}
else
{
expand = ImGui::TreeNode( frameName );
}
if( isKernel || frameName[0] == '[' ) ImGui::PopStyleColor();
ImGui::PopID();
}
if( m_callstackTreeBuzzAnim.Match( idx ) )
{
const auto time = m_callstackTreeBuzzAnim.Time();
const auto indentVal = sin( time * 60.f ) * 10.f * time;
ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );
}
else
{
ImGui::SameLine();
}
const char* fileName = nullptr;
if( frame.line == 0 )
{
TextDisabledUnformatted( m_worker.GetString( frameDataPtr->imageName ) );
}
else
{
fileName = m_worker.GetString( frame.file );
ImGui::TextDisabled( "%s:%i", fileName, frame.line );
}
if( ImGui::IsItemHovered() )
{
DrawSourceTooltip( fileName, frame.line );
if( ImGui::IsItemClicked( 1 ) )
{
if( !ViewDispatch( fileName, frame.line, frame.symAddr ) )
{
m_callstackTreeBuzzAnim.Enable( idx, 0.5f );
}
}
}
ImGui::SameLine();
if( v.children.empty() )
{
ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "(%s)", RealToString( v.count ) );
}
else
{
ImGui::TextColored( ImVec4( 0.8, 0.8, 0.2, 1.0 ), "(%s)", RealToString( v.count ) );
}
if( expand )
{
DrawParentsFrameTreeLevel( v.children, idx );
ImGui::TreePop();
}
}
}
}
void View::DrawAllocList()
{
const auto scale = GetScale();

View File

@ -237,6 +237,10 @@ private:
unordered_flat_map<uint64_t, CallstackFrameTree> GetCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const;
void DrawFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx );
unordered_flat_map<uint64_t, CallstackFrameTree> GetParentsCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const;
unordered_flat_map<uint64_t, CallstackFrameTree> GetParentsCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const;
void DrawParentsFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx );
void DrawInfoWindow();
void DrawZoneInfoWindow();
void DrawGpuInfoWindow();
@ -775,6 +779,9 @@ private:
uint64_t symAddr = 0;
int sel;
bool withInlines = false;
int mode = 0;
bool groupBottomUp = true;
bool groupTopDown = true;
} m_sampleParents;
std::vector<std::pair<int, int>> m_cpuUsageBuf;