Transfer, display, save CPU topology data.

This commit is contained in:
Bartosz Taudul 2019-11-29 22:41:41 +01:00
parent 5148ecdc50
commit 712403e9fd
7 changed files with 156 additions and 9 deletions

View File

@ -2450,6 +2450,13 @@ void Profiler::CalibrateDelay()
void Profiler::ReportTopology()
{
struct CpuData
{
uint32_t package;
uint32_t core;
uint32_t thread;
};
#if defined _WIN32 || defined __CYGWIN__
# ifdef UNICODE
t_GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx = (t_GetLogicalProcessorInformationEx)GetProcAddress( GetModuleHandle( L"kernel32" ), "GetLogicalProcessorInformationEx" );
@ -2475,13 +2482,6 @@ void Profiler::ReportTopology()
GetSystemInfo( &sysinfo );
const uint32_t numcpus = sysinfo.dwNumberOfProcessors;
struct CpuData
{
uint32_t package;
uint32_t core;
uint32_t thread;
};
auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus );
for( uint32_t i=0; i<numcpus; i++ ) cpuData[i].thread = i;
@ -2521,6 +2521,26 @@ void Profiler::ReportTopology()
idx++;
}
Magic magic;
auto token = GetToken();
for( uint32_t i=0; i<numcpus; i++ )
{
auto& data = cpuData[i];
auto& tail = token->get_tail_index();
auto item = token->enqueue_begin( magic );
MemWrite( &item->hdr.type, QueueType::CpuTopology );
MemWrite( &item->cpuTopology.package, data.package );
MemWrite( &item->cpuTopology.core, data.core );
MemWrite( &item->cpuTopology.thread, data.thread );
#ifdef TRACY_ON_DEMAND
DeferItem( *item );
#endif
tail.store( magic + 1, std::memory_order_release );
}
tracy_free( cpuData );
tracy_free( coreInfo );
tracy_free( packageInfo );

View File

@ -9,7 +9,7 @@ namespace tracy
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
enum : uint32_t { ProtocolVersion = 24 };
enum : uint32_t { ProtocolVersion = 25 };
enum : uint32_t { BroadcastVersion = 0 };
using lz4sz_t = uint32_t;

View File

@ -68,6 +68,7 @@ enum class QueueType : uint8_t
TidToPid,
PlotConfig,
ParamSetup,
CpuTopology,
StringData,
ThreadName,
CustomStringData,
@ -357,6 +358,13 @@ struct QueueParamSetup
int32_t val;
};
struct QueueCpuTopology
{
uint32_t package;
uint32_t core;
uint32_t thread;
};
struct QueueHeader
{
union
@ -407,6 +415,7 @@ struct QueueItem
QueueTidToPid tidToPid;
QueuePlotConfig plotConfig;
QueueParamSetup paramSetup;
QueueCpuTopology cpuTopology;
};
};
#pragma pack()
@ -476,6 +485,7 @@ static const size_t QueueDataSize[] = {
sizeof( QueueHeader ) + sizeof( QueueTidToPid ),
sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),
sizeof( QueueHeader ) + sizeof( QueueParamSetup ),
sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),
// keep all QueueStringTransfer below
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name

View File

@ -7,7 +7,7 @@ namespace Version
{
enum { Major = 0 };
enum { Minor = 6 };
enum { Patch = 1 };
enum { Patch = 2 };
}
}

View File

@ -11390,6 +11390,59 @@ void View::DrawInfo()
ImGui::TreePop();
}
auto& topology = m_worker.GetCpuTopology();
if( !topology.empty() )
{
if( ImGui::TreeNode( "CPU topology" ) )
{
std::vector<decltype(topology.begin())> tsort;
tsort.reserve( topology.size() );
for( auto it = topology.begin(); it != topology.end(); ++it ) tsort.emplace_back( it );
std::sort( tsort.begin(), tsort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
char buf[128];
for( auto& package : tsort )
{
#ifdef TRACY_EXTENDED_FONT
sprintf( buf, ICON_FA_BOX " Package %i", package->first );
#else
sprintf( buf, "Package %i", package->first );
#endif
if( ImGui::TreeNodeEx( buf, ImGuiTreeNodeFlags_DefaultOpen ) )
{
std::vector<decltype(package->second.begin())> csort;
csort.reserve( package->second.size() );
for( auto it = package->second.begin(); it != package->second.end(); ++it ) csort.emplace_back( it );
std::sort( csort.begin(), csort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
for( auto& core : csort )
{
#ifdef TRACY_EXTENDED_FONT
sprintf( buf, ICON_FA_MICROCHIP " Core %i", core->first );
#else
sprintf( buf, "Core %i", core->first );
#endif
if( ImGui::TreeNodeEx( buf, ImGuiTreeNodeFlags_DefaultOpen ) )
{
ImGui::Indent();
for( auto& thread : core->second )
{
#ifdef TRACY_EXTENDED_FONT
sprintf( buf, ICON_FA_RANDOM " Thread %i", thread );
#else
sprintf( buf, "Thread %i", thread );
#endif
ImGui::TextUnformatted( buf );
}
ImGui::Unindent();
ImGui::TreePop();
}
}
ImGui::TreePop();
}
}
ImGui::TreePop();
}
}
ImGui::Separator();
TextFocused( "PID:", RealToString( m_worker.GetPid(), true ) );
TextFocused( "Host info:", m_worker.GetHostInfo().c_str() );

View File

@ -343,6 +343,34 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
m_hostInfo = std::string( tmp, tmp+sz );
}
if( fileVer >= FileVersion( 0, 6, 2 ) )
{
f.Read( sz );
m_data.cpuTopology.reserve( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint32_t packageId;
uint64_t psz;
f.Read2( packageId, psz );
auto& package = *m_data.cpuTopology.emplace( packageId, flat_hash_map<uint32_t, std::vector<uint32_t>> {} ).first;
package.second.reserve( psz );
for( uint64_t j=0; j<psz; j++ )
{
uint32_t coreId;
uint64_t csz;
f.Read2( coreId, csz );
auto& core = *package.second.emplace( coreId, std::vector<uint32_t> {} ).first;
core.second.reserve( csz );
for( uint64_t k=0; k<csz; k++ )
{
uint32_t thread;
f.Read( thread );
core.second.emplace_back( thread );
}
}
}
}
f.Read( &m_data.crashEvent, sizeof( m_data.crashEvent ) );
f.Read( sz );
@ -3238,6 +3266,9 @@ bool Worker::Process( const QueueItem& ev )
case QueueType::ParamSetup:
ProcessParamSetup( ev.paramSetup );
break;
case QueueType::CpuTopology:
ProcessCpuTopology( ev.cpuTopology );
break;
default:
assert( false );
break;
@ -4584,6 +4615,15 @@ void Worker::ProcessParamSetup( const QueueParamSetup& ev )
m_params.push_back( Parameter { ev.idx, StringRef( StringRef::Ptr, ev.name ), bool( ev.isBool ), ev.val } );
}
void Worker::ProcessCpuTopology( const QueueCpuTopology& ev )
{
auto package = m_data.cpuTopology.find( ev.package );
if( package == m_data.cpuTopology.end() ) package = m_data.cpuTopology.emplace( ev.package, flat_hash_map<uint32_t, std::vector<uint32_t>> {} ).first;
auto core = package->second.find( ev.core );
if( core == package->second.end() ) core = package->second.emplace( ev.core, std::vector<uint32_t> {} ).first;
core->second.emplace_back( ev.thread );
}
void Worker::MemAllocChanged( int64_t time )
{
const auto val = (double)m_data.memory.usage;
@ -5171,6 +5211,25 @@ void Worker::Write( FileWrite& f )
f.Write( &sz, sizeof( sz ) );
f.Write( m_hostInfo.c_str(), sz );
sz = m_data.cpuTopology.size();
f.Write( &sz, sizeof( sz ) );
for( auto& package : m_data.cpuTopology )
{
sz = package.second.size();
f.Write( &package.first, sizeof( package.first ) );
f.Write( &sz, sizeof( sz ) );
for( auto& core : package.second )
{
sz = core.second.size();
f.Write( &core.first, sizeof( core.first ) );
f.Write( &sz, sizeof( sz ) );
for( auto& thread : core.second )
{
f.Write( &thread, sizeof( thread ) );
}
}
}
f.Write( &m_data.crashEvent, sizeof( m_data.crashEvent ) );
sz = m_data.frames.Data().size();

View File

@ -228,6 +228,8 @@ private:
Vector<ContextSwitchUsage> ctxUsage;
bool ctxUsageReady = false;
#endif
flat_hash_map<uint32_t, flat_hash_map<uint32_t, std::vector<uint32_t>>> cpuTopology;
};
struct MbpsBlock
@ -422,6 +424,8 @@ public:
const Vector<Parameter>& GetParameters() const { return m_params; }
void SetParameter( size_t paramIdx, int32_t val );
const decltype(DataBlock::cpuTopology)& GetCpuTopology() const { return m_data.cpuTopology; }
private:
void Network();
void Exec();
@ -483,6 +487,7 @@ private:
tracy_force_inline void ProcessThreadWakeup( const QueueThreadWakeup& ev );
tracy_force_inline void ProcessTidToPid( const QueueTidToPid& ev );
tracy_force_inline void ProcessParamSetup( const QueueParamSetup& ev );
tracy_force_inline void ProcessCpuTopology( const QueueCpuTopology& ev );
tracy_force_inline ZoneEvent* AllocZoneEvent();
tracy_force_inline void ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev );