mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-29 08:54:34 +00:00
Extract CPU data UI from View.
This commit is contained in:
parent
6f99c8d055
commit
5a3305095e
@ -139,6 +139,7 @@
|
|||||||
<ClCompile Include="..\..\..\server\TracyView.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyView_Compare.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView_Compare.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyView_ContextSwitch.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView_ContextSwitch.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyView_CpuData.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyView_FindZone.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView_FindZone.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyView_Navigation.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView_Navigation.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyView_Options.cpp" />
|
<ClCompile Include="..\..\..\server\TracyView_Options.cpp" />
|
||||||
|
@ -276,6 +276,9 @@
|
|||||||
<ClCompile Include="..\..\..\server\TracyView_TraceInfo.cpp">
|
<ClCompile Include="..\..\..\server\TracyView_TraceInfo.cpp">
|
||||||
<Filter>server</Filter>
|
<Filter>server</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyView_CpuData.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
||||||
|
@ -7951,305 +7951,6 @@ void View::DrawLockInfoWindow()
|
|||||||
if( !visible ) m_lockInfoWindow = InvalidId;
|
if( !visible ) m_lockInfoWindow = InvalidId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::DrawCpuDataWindow()
|
|
||||||
{
|
|
||||||
const auto scale = GetScale();
|
|
||||||
ImGui::SetNextWindowSize( ImVec2( 700 * scale, 800 * scale ), ImGuiCond_FirstUseEver );
|
|
||||||
ImGui::Begin( "CPU data", &m_showCpuDataWindow );
|
|
||||||
if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
|
|
||||||
|
|
||||||
struct PidData
|
|
||||||
{
|
|
||||||
std::vector<uint64_t> tids;
|
|
||||||
CpuThreadData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto& ctd = m_worker.GetCpuThreadData();
|
|
||||||
unordered_flat_map<uint64_t, PidData> pids;
|
|
||||||
for( auto& v : ctd )
|
|
||||||
{
|
|
||||||
uint64_t pid = m_worker.GetPidFromTid( v.first );
|
|
||||||
auto it = pids.find( pid );
|
|
||||||
if( it == pids.end() )
|
|
||||||
{
|
|
||||||
it = pids.emplace( pid, PidData {} ).first;
|
|
||||||
}
|
|
||||||
it->second.tids.emplace_back( v.first );
|
|
||||||
it->second.data.runningTime += v.second.runningTime;
|
|
||||||
it->second.data.runningRegions += v.second.runningRegions;
|
|
||||||
it->second.data.migrations += v.second.migrations;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFocused( "Tracked threads:", RealToString( ctd.size() ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
TextFocused( "Tracked processes:", RealToString( pids.size() ) );
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::BeginChild( "##cpudata" );
|
|
||||||
if( ImGui::BeginTable( "##cpudata", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )
|
|
||||||
{
|
|
||||||
ImGui::TableSetupScrollFreeze( 0, 1 );
|
|
||||||
ImGui::TableSetupColumn( "PID/TID", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
|
||||||
ImGui::TableSetupColumn( "Name" );
|
|
||||||
ImGui::TableSetupColumn( "Running time", ImGuiTableColumnFlags_PreferSortDescending );
|
|
||||||
ImGui::TableSetupColumn( "Running regions", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
|
||||||
ImGui::TableSetupColumn( "CPU migrations", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
|
||||||
ImGui::TableHeadersRow();
|
|
||||||
|
|
||||||
std::vector<unordered_flat_map<uint64_t, PidData>::iterator> psort;
|
|
||||||
psort.reserve( pids.size() );
|
|
||||||
for( auto it = pids.begin(); it != pids.end(); ++it ) psort.emplace_back( it );
|
|
||||||
const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;
|
|
||||||
switch( sortspec.ColumnIndex )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first > r->first; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) > 0; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) < 0; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime > r->second.data.runningTime; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime < r->second.data.runningTime; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions > r->second.data.runningRegions; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions < r->second.data.runningRegions; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations > r->second.data.migrations; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations < r->second.data.migrations; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert( false );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto thisPid = m_worker.GetPid();
|
|
||||||
const auto rtimespan = 1.0 / m_worker.GetLastTime();
|
|
||||||
const auto ty = ImGui::GetTextLineHeight();
|
|
||||||
|
|
||||||
auto& style = ImGui::GetStyle();
|
|
||||||
const auto framePaddingY = style.FramePadding.y;
|
|
||||||
for( auto& pidit : psort )
|
|
||||||
{
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
|
|
||||||
char buf[128];
|
|
||||||
auto& pid = *pidit;
|
|
||||||
const auto pidMatch = thisPid != 0 && thisPid == pid.first;
|
|
||||||
auto name = m_worker.GetExternalName( pid.second.tids[0] ).first;
|
|
||||||
if( pidMatch )
|
|
||||||
{
|
|
||||||
name = m_worker.GetCaptureProgram().c_str();
|
|
||||||
ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.2f, 1.0f, 0.2f, 1.0f ) );
|
|
||||||
}
|
|
||||||
const auto pidtxt = pid.first == 0 ? "Unknown" : RealToString( pid.first );
|
|
||||||
const auto expand = ImGui::TreeNode( pidtxt );
|
|
||||||
if( ImGui::IsItemHovered() )
|
|
||||||
{
|
|
||||||
if( pidMatch )
|
|
||||||
{
|
|
||||||
m_drawThreadMigrations = pid.first;
|
|
||||||
m_cpuDataThread = pid.first;
|
|
||||||
}
|
|
||||||
m_drawThreadHighlight = pid.first;
|
|
||||||
}
|
|
||||||
const auto tsz = pid.second.tids.size();
|
|
||||||
if( tsz > 1 )
|
|
||||||
{
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::TextDisabled( "(%s)", RealToString( tsz ) );
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted( pid.first == 0 ? "???" : name );
|
|
||||||
if( ImGui::IsItemHovered() )
|
|
||||||
{
|
|
||||||
if( pidMatch )
|
|
||||||
{
|
|
||||||
m_drawThreadMigrations = pid.first;
|
|
||||||
m_cpuDataThread = pid.first;
|
|
||||||
}
|
|
||||||
m_drawThreadHighlight = pid.first;
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
PrintStringPercent( buf, TimeToString( pid.second.data.runningTime ), double( pid.second.data.runningTime ) * rtimespan * 100 );
|
|
||||||
style.FramePadding.y = 0;
|
|
||||||
ImGui::ProgressBar( double( pid.second.data.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
|
|
||||||
style.FramePadding.y = framePaddingY;
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted( RealToString( pid.second.data.runningRegions ) );
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted( RealToString( pid.second.data.migrations ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
PrintStringPercent( buf, double( pid.second.data.migrations ) / pid.second.data.runningRegions * 100 );
|
|
||||||
TextDisabledUnformatted( buf );
|
|
||||||
if( expand )
|
|
||||||
{
|
|
||||||
ImGui::Separator();
|
|
||||||
switch( sortspec.ColumnIndex )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), []( const auto& l, const auto& r ) { return l > r; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end() );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) > 0; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) < 0; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime > ctd.find( r )->second.runningTime; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime < ctd.find( r )->second.runningTime; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions > ctd.find( r )->second.runningRegions; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions < ctd.find( r )->second.runningRegions; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations > ctd.find( r )->second.migrations; } );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations < ctd.find( r )->second.migrations; } );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert( false );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for( auto& tid : pid.second.tids )
|
|
||||||
{
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
|
|
||||||
const auto tidMatch = pidMatch && m_worker.IsThreadLocal( tid );
|
|
||||||
const char* tname;
|
|
||||||
if( tidMatch )
|
|
||||||
{
|
|
||||||
tname = m_worker.GetThreadName( tid );
|
|
||||||
ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 1.0f, 0.2f, 1.0f ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tname = m_worker.GetExternalName( tid ).second;
|
|
||||||
}
|
|
||||||
const auto& tit = ctd.find( tid );
|
|
||||||
assert( tit != ctd.end() );
|
|
||||||
ImGui::TextUnformatted( RealToString( tid ) );
|
|
||||||
if( ImGui::IsItemHovered() )
|
|
||||||
{
|
|
||||||
if( tidMatch )
|
|
||||||
{
|
|
||||||
m_drawThreadMigrations = tid;
|
|
||||||
m_cpuDataThread = tid;
|
|
||||||
}
|
|
||||||
m_drawThreadHighlight = tid;
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if( tidMatch )
|
|
||||||
{
|
|
||||||
SmallColorBox( GetThreadColor( tid, 0 ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
}
|
|
||||||
ImGui::TextUnformatted( tname );
|
|
||||||
if( ImGui::IsItemHovered() )
|
|
||||||
{
|
|
||||||
if( tidMatch )
|
|
||||||
{
|
|
||||||
m_drawThreadMigrations = tid;
|
|
||||||
m_cpuDataThread = tid;
|
|
||||||
}
|
|
||||||
m_drawThreadHighlight = tid;
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
PrintStringPercent( buf, TimeToString( tit->second.runningTime ), double( tit->second.runningTime ) * rtimespan * 100 );
|
|
||||||
style.FramePadding.y = 0;
|
|
||||||
ImGui::ProgressBar( double( tit->second.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
|
|
||||||
style.FramePadding.y = framePaddingY;
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted( RealToString( tit->second.runningRegions ) );
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted( RealToString( tit->second.migrations ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
PrintStringPercent( buf, double( tit->second.migrations ) / tit->second.runningRegions * 100 );
|
|
||||||
TextDisabledUnformatted( buf );
|
|
||||||
if( tidMatch )
|
|
||||||
{
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::TreePop();
|
|
||||||
ImGui::Separator();
|
|
||||||
}
|
|
||||||
if( pidMatch )
|
|
||||||
{
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::DrawSelectedAnnotation()
|
void View::DrawSelectedAnnotation()
|
||||||
{
|
{
|
||||||
assert( m_selectedAnnotation );
|
assert( m_selectedAnnotation );
|
||||||
|
307
server/TracyView_CpuData.cpp
Normal file
307
server/TracyView_CpuData.cpp
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
#include "TracyPrint.hpp"
|
||||||
|
#include "TracyView.hpp"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
void View::DrawCpuDataWindow()
|
||||||
|
{
|
||||||
|
const auto scale = GetScale();
|
||||||
|
ImGui::SetNextWindowSize( ImVec2( 700 * scale, 800 * scale ), ImGuiCond_FirstUseEver );
|
||||||
|
ImGui::Begin( "CPU data", &m_showCpuDataWindow );
|
||||||
|
if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
|
||||||
|
|
||||||
|
struct PidData
|
||||||
|
{
|
||||||
|
std::vector<uint64_t> tids;
|
||||||
|
CpuThreadData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto& ctd = m_worker.GetCpuThreadData();
|
||||||
|
unordered_flat_map<uint64_t, PidData> pids;
|
||||||
|
for( auto& v : ctd )
|
||||||
|
{
|
||||||
|
uint64_t pid = m_worker.GetPidFromTid( v.first );
|
||||||
|
auto it = pids.find( pid );
|
||||||
|
if( it == pids.end() )
|
||||||
|
{
|
||||||
|
it = pids.emplace( pid, PidData {} ).first;
|
||||||
|
}
|
||||||
|
it->second.tids.emplace_back( v.first );
|
||||||
|
it->second.data.runningTime += v.second.runningTime;
|
||||||
|
it->second.data.runningRegions += v.second.runningRegions;
|
||||||
|
it->second.data.migrations += v.second.migrations;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFocused( "Tracked threads:", RealToString( ctd.size() ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
TextFocused( "Tracked processes:", RealToString( pids.size() ) );
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::BeginChild( "##cpudata" );
|
||||||
|
if( ImGui::BeginTable( "##cpudata", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )
|
||||||
|
{
|
||||||
|
ImGui::TableSetupScrollFreeze( 0, 1 );
|
||||||
|
ImGui::TableSetupColumn( "PID/TID", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
||||||
|
ImGui::TableSetupColumn( "Name" );
|
||||||
|
ImGui::TableSetupColumn( "Running time", ImGuiTableColumnFlags_PreferSortDescending );
|
||||||
|
ImGui::TableSetupColumn( "Running regions", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
||||||
|
ImGui::TableSetupColumn( "CPU migrations", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
std::vector<unordered_flat_map<uint64_t, PidData>::iterator> psort;
|
||||||
|
psort.reserve( pids.size() );
|
||||||
|
for( auto it = pids.begin(); it != pids.end(); ++it ) psort.emplace_back( it );
|
||||||
|
const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;
|
||||||
|
switch( sortspec.ColumnIndex )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first > r->first; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) > 0; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) < 0; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime > r->second.data.runningTime; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime < r->second.data.runningTime; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions > r->second.data.runningRegions; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions < r->second.data.runningRegions; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations > r->second.data.migrations; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations < r->second.data.migrations; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert( false );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto thisPid = m_worker.GetPid();
|
||||||
|
const auto rtimespan = 1.0 / m_worker.GetLastTime();
|
||||||
|
const auto ty = ImGui::GetTextLineHeight();
|
||||||
|
|
||||||
|
auto& style = ImGui::GetStyle();
|
||||||
|
const auto framePaddingY = style.FramePadding.y;
|
||||||
|
for( auto& pidit : psort )
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
auto& pid = *pidit;
|
||||||
|
const auto pidMatch = thisPid != 0 && thisPid == pid.first;
|
||||||
|
auto name = m_worker.GetExternalName( pid.second.tids[0] ).first;
|
||||||
|
if( pidMatch )
|
||||||
|
{
|
||||||
|
name = m_worker.GetCaptureProgram().c_str();
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.2f, 1.0f, 0.2f, 1.0f ) );
|
||||||
|
}
|
||||||
|
const auto pidtxt = pid.first == 0 ? "Unknown" : RealToString( pid.first );
|
||||||
|
const auto expand = ImGui::TreeNode( pidtxt );
|
||||||
|
if( ImGui::IsItemHovered() )
|
||||||
|
{
|
||||||
|
if( pidMatch )
|
||||||
|
{
|
||||||
|
m_drawThreadMigrations = pid.first;
|
||||||
|
m_cpuDataThread = pid.first;
|
||||||
|
}
|
||||||
|
m_drawThreadHighlight = pid.first;
|
||||||
|
}
|
||||||
|
const auto tsz = pid.second.tids.size();
|
||||||
|
if( tsz > 1 )
|
||||||
|
{
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled( "(%s)", RealToString( tsz ) );
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted( pid.first == 0 ? "???" : name );
|
||||||
|
if( ImGui::IsItemHovered() )
|
||||||
|
{
|
||||||
|
if( pidMatch )
|
||||||
|
{
|
||||||
|
m_drawThreadMigrations = pid.first;
|
||||||
|
m_cpuDataThread = pid.first;
|
||||||
|
}
|
||||||
|
m_drawThreadHighlight = pid.first;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
PrintStringPercent( buf, TimeToString( pid.second.data.runningTime ), double( pid.second.data.runningTime ) * rtimespan * 100 );
|
||||||
|
style.FramePadding.y = 0;
|
||||||
|
ImGui::ProgressBar( double( pid.second.data.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
|
||||||
|
style.FramePadding.y = framePaddingY;
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted( RealToString( pid.second.data.runningRegions ) );
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted( RealToString( pid.second.data.migrations ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
PrintStringPercent( buf, double( pid.second.data.migrations ) / pid.second.data.runningRegions * 100 );
|
||||||
|
TextDisabledUnformatted( buf );
|
||||||
|
if( expand )
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
switch( sortspec.ColumnIndex )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), []( const auto& l, const auto& r ) { return l > r; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end() );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) > 0; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) < 0; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime > ctd.find( r )->second.runningTime; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime < ctd.find( r )->second.runningTime; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions > ctd.find( r )->second.runningRegions; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions < ctd.find( r )->second.runningRegions; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if( sortspec.SortDirection == ImGuiSortDirection_Descending )
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations > ctd.find( r )->second.migrations; } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations < ctd.find( r )->second.migrations; } );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert( false );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for( auto& tid : pid.second.tids )
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
const auto tidMatch = pidMatch && m_worker.IsThreadLocal( tid );
|
||||||
|
const char* tname;
|
||||||
|
if( tidMatch )
|
||||||
|
{
|
||||||
|
tname = m_worker.GetThreadName( tid );
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 1.0f, 0.2f, 1.0f ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tname = m_worker.GetExternalName( tid ).second;
|
||||||
|
}
|
||||||
|
const auto& tit = ctd.find( tid );
|
||||||
|
assert( tit != ctd.end() );
|
||||||
|
ImGui::TextUnformatted( RealToString( tid ) );
|
||||||
|
if( ImGui::IsItemHovered() )
|
||||||
|
{
|
||||||
|
if( tidMatch )
|
||||||
|
{
|
||||||
|
m_drawThreadMigrations = tid;
|
||||||
|
m_cpuDataThread = tid;
|
||||||
|
}
|
||||||
|
m_drawThreadHighlight = tid;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if( tidMatch )
|
||||||
|
{
|
||||||
|
SmallColorBox( GetThreadColor( tid, 0 ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
ImGui::TextUnformatted( tname );
|
||||||
|
if( ImGui::IsItemHovered() )
|
||||||
|
{
|
||||||
|
if( tidMatch )
|
||||||
|
{
|
||||||
|
m_drawThreadMigrations = tid;
|
||||||
|
m_cpuDataThread = tid;
|
||||||
|
}
|
||||||
|
m_drawThreadHighlight = tid;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
PrintStringPercent( buf, TimeToString( tit->second.runningTime ), double( tit->second.runningTime ) * rtimespan * 100 );
|
||||||
|
style.FramePadding.y = 0;
|
||||||
|
ImGui::ProgressBar( double( tit->second.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
|
||||||
|
style.FramePadding.y = framePaddingY;
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted( RealToString( tit->second.runningRegions ) );
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted( RealToString( tit->second.migrations ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
PrintStringPercent( buf, double( tit->second.migrations ) / tit->second.runningRegions * 100 );
|
||||||
|
TextDisabledUnformatted( buf );
|
||||||
|
if( tidMatch )
|
||||||
|
{
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
if( pidMatch )
|
||||||
|
{
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user