From fe7f56b022743352da02db021160cb0ccdf9de64 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Fri, 16 Aug 2019 19:22:23 +0200 Subject: [PATCH] Implement retrieval of external process names. --- client/TracyProfiler.cpp | 6 ++++- client/TracyProfiler.hpp | 3 ++- client/TracySysTrace.cpp | 39 +++++++++++++++++++++++++++++-- client/TracySysTrace.hpp | 4 ++++ common/TracyProtocol.hpp | 3 ++- common/TracyQueue.hpp | 2 ++ server/TracyView.cpp | 50 ++++++++++++++++++++-------------------- server/TracyWorker.cpp | 47 ++++++++++++++++++++++++++++++++++--- server/TracyWorker.hpp | 5 ++++ 9 files changed, 126 insertions(+), 33 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 4ab089c6..23a8722e 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -56,6 +56,7 @@ #include "TracyProfiler.hpp" #include "TracyThread.hpp" #include "TracyArmCpuTable.hpp" +#include "TracySysTrace.hpp" #include "../TracyC.h" #ifdef __APPLE__ @@ -1851,7 +1852,7 @@ bool Profiler::SendData( const char* data, size_t len ) void Profiler::SendString( uint64_t str, const char* ptr, QueueType type ) { - assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData || type == QueueType::PlotName || type == QueueType::FrameName ); + assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData || type == QueueType::PlotName || type == QueueType::FrameName || type == QueueType::ExternalName ); QueueItem item; MemWrite( &item.hdr.type, type ); @@ -2050,6 +2051,9 @@ bool Profiler::HandleServerQuery() case ServerQueryDisconnect: HandleDisconnect(); return false; + case ServerQueryExternalName: + SysTraceSendExternalName( ptr ); + break; default: assert( false ); break; diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 844a53ae..6f6d9a5d 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -442,6 +442,8 @@ public: void RequestShutdown() { m_shutdown.store( true, std::memory_order_relaxed ); m_shutdownManual.store( true, std::memory_order_relaxed ); } bool HasShutdownFinished() const { return m_shutdownFinished.load( std::memory_order_relaxed ); } + void SendString( uint64_t ptr, const char* str, QueueType type ); + private: enum class DequeueStatus { Success, ConnectionLost, QueueEmpty }; @@ -467,7 +469,6 @@ private: } bool SendData( const char* data, size_t len ); - void SendString( uint64_t ptr, const char* str, QueueType type ); void SendLongString( uint64_t ptr, const char* str, size_t len, QueueType type ); void SendSourceLocation( uint64_t ptr ); void SendSourceLocationPayload( uint64_t ptr ); diff --git a/client/TracySysTrace.cpp b/client/TracySysTrace.cpp index a2bd29e4..f26f92f5 100644 --- a/client/TracySysTrace.cpp +++ b/client/TracySysTrace.cpp @@ -6,11 +6,11 @@ # define INITGUID # include -# include # include # include # include # include +# include # include "../common/TracyAlloc.hpp" # include "../common/TracySystem.hpp" @@ -156,6 +156,36 @@ void SysTraceWorker( void* ptr ) tracy_free( s_prop ); } +void SysTraceSendExternalName( uint64_t thread ) +{ + const auto hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, thread ); + if( hnd != INVALID_HANDLE_VALUE ) + { + const auto pid = GetProcessIdOfThread( hnd ); + CloseHandle( hnd ); + if( pid != 0 ) + { + const auto phnd = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid ); + if( phnd != INVALID_HANDLE_VALUE ) + { + char buf[1024]; + const auto sz = GetProcessImageFileNameA( phnd, buf, 1024 ); + CloseHandle( phnd ); + if( sz != 0 ) + { + auto ptr = buf + sz - 1; + while( ptr > buf && *ptr != '\\' ) ptr--; + if( *ptr == '\\' ) ptr++; + GetProfiler().SendString( thread, ptr, QueueType::ExternalName ); + return; + } + } + } + } + + GetProfiler().SendString( thread, "???", QueueType::ExternalName ); +} + } # elif defined __linux__ @@ -163,7 +193,6 @@ void SysTraceWorker( void* ptr ) # include # include # include -# include # include # include # include @@ -342,6 +371,12 @@ void SysTraceWorker( void* ptr ) fclose( f ); } +void SysTraceSendExternalName( uint64_t thread ) +{ + // TODO + GetProfiler().SendString( thread, "???", QueueType::ExternalName ); +} + } # endif diff --git a/client/TracySysTrace.hpp b/client/TracySysTrace.hpp index fd2978ca..b5933faf 100644 --- a/client/TracySysTrace.hpp +++ b/client/TracySysTrace.hpp @@ -7,6 +7,8 @@ #ifdef TRACY_HAS_SYSTEM_TRACING +#include + namespace tracy { @@ -14,6 +16,8 @@ bool SysTraceStart(); void SysTraceStop(); void SysTraceWorker( void* ptr ); +void SysTraceSendExternalName( uint64_t thread ); + } #endif diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index 4cf1bafc..e0dfacc1 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -45,7 +45,8 @@ enum ServerQuery : uint8_t ServerQueryPlotName, ServerQueryCallstackFrame, ServerQueryFrameName, - ServerQueryDisconnect + ServerQueryDisconnect, + ServerQueryExternalName }; struct ServerQueryPacket diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index cf7f61fb..9ca10373 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -66,6 +66,7 @@ enum class QueueType : uint8_t CallstackAllocPayload, FrameName, FrameImageData, + ExternalName, NUM_TYPES }; @@ -424,6 +425,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack alloc payload sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame name sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame image data + sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name }; static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" ); diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 453ee3c1..e7d0d992 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3967,47 +3967,45 @@ int View::DrawCpuData( int offset, double pxns, const ImVec2& wpos, bool hover, ZoomToRange( start, rend ); } } - } else { const auto thread = it->Thread(); - const auto local = thread != 0 && m_worker.IsThreadLocal( thread ); + const auto local = m_worker.IsThreadLocal( thread ); const auto pr0 = ( start - m_zvStart ) * pxns; const auto pr1 = ( end - m_zvStart ) * pxns; const auto px0 = std::max( pr0, -10.0 ); const auto px1 = std::max( { std::min( pr1, double( w + 10 ) ), px0 + pxns * 0.5, px0 + MinVisSize } ); draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), local ? 0xFF334488 : 0xFF444444 ); draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), local ? 0xFF5566AA : 0xFF666666 ); - if( local ) + + auto txt = local ? m_worker.GetThreadString( thread ) : m_worker.GetExternalName( thread ); + auto tsz = ImGui::CalcTextSize( txt ); + if( tsz.x < zsz ) { - auto txt = m_worker.GetThreadString( thread ); - auto tsz = ImGui::CalcTextSize( txt ); - if( tsz.x < zsz ) + const auto x = ( start - m_zvStart ) * pxns + ( ( end - start ) * pxns - tsz.x ) / 2; + if( x < 0 || x > w - tsz.x ) { - const auto x = ( start - m_zvStart ) * pxns + ( ( end - start ) * pxns - tsz.x ) / 2; - if( x < 0 || x > w - tsz.x ) - { - ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true ); - DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset-1 ), 0xFFFFFFFF, txt ); - ImGui::PopClipRect(); - } - else if( start == end ) - { - DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset-1 ), 0xFFFFFFFF, txt ); - } - else - { - DrawTextContrast( draw, wpos + ImVec2( x, offset-1 ), 0xFFFFFFFF, txt ); - } + ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true ); + DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, txt ); + ImGui::PopClipRect(); + } + else if( start == end ) + { + DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, txt ); } else { - ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true ); - DrawTextContrast( draw, wpos + ImVec2( ( start - m_zvStart ) * pxns, offset ), 0xFFFFFFFF, txt ); - ImGui::PopClipRect(); + DrawTextContrast( draw, wpos + ImVec2( x, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, txt ); } } + else + { + ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true ); + DrawTextContrast( draw, wpos + ImVec2( ( start - m_zvStart ) * pxns, offset ), local ? 0xFFFFFFFF : 0xAAFFFFFF, txt ); + ImGui::PopClipRect(); + } + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( px1, offset + sty - 1 ) ) ) { ImGui::PopFont(); @@ -4022,7 +4020,9 @@ int View::DrawCpuData( int offset, double pxns, const ImVec2& wpos, bool hover, } else { - TextFocused( "Program:", "" ); + TextFocused( "Program:", txt ); + ImGui::SameLine(); + TextDisabledUnformatted( "(external)" ); } ImGui::Separator(); TextFocused( "Start time:", TimeToString( start ) ); diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 19cedb9b..0d2bb436 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -246,6 +246,7 @@ Worker::Worker( const char* addr ) , m_bufferOffset( 0 ) , m_pendingStrings( 0 ) , m_pendingThreads( 0 ) + , m_pendingExternalNames( 0 ) , m_pendingSourceLocation( 0 ) , m_pendingCallstackFrames( 0 ) , m_pendingCallstackSubframes( 0 ) @@ -1838,6 +1839,19 @@ const SourceLocation& Worker::GetSourceLocation( int16_t srcloc ) const } } +const char* Worker::GetExternalName( uint64_t id ) const +{ + const auto it = m_data.externalNames.find( id ); + if( it == m_data.externalNames.end() ) + { + return "???"; + } + else + { + return it->second; + } +} + const char* Worker::GetZoneName( const SourceLocation& srcloc ) const { if( srcloc.name.active ) @@ -2160,7 +2174,7 @@ void Worker::Exec() { if( m_pendingStrings != 0 || m_pendingThreads != 0 || m_pendingSourceLocation != 0 || m_pendingCallstackFrames != 0 || !m_pendingCustomStrings.empty() || m_data.plots.IsPending() || m_pendingCallstackPtr != 0 || - m_pendingCallstackSubframes != 0 || !m_pendingFrameImageData.empty() ) + m_pendingExternalNames != 0 || m_pendingCallstackSubframes != 0 || !m_pendingFrameImageData.empty() ) { continue; } @@ -2255,6 +2269,9 @@ bool Worker::DispatchProcess( const QueueItem& ev, char*& ptr ) case QueueType::CallstackAllocPayload: AddCallstackAllocPayload( ev.stringTransfer.ptr, ptr, sz ); break; + case QueueType::ExternalName: + AddExternalName( ev.stringTransfer.ptr, ptr, sz ); + break; default: assert( false ); break; @@ -2483,6 +2500,16 @@ void Worker::CheckThreadString( uint64_t id ) Query( ServerQueryThreadString, id ); } +void Worker::CheckExternalName( uint64_t id ) +{ + if( m_data.externalNames.find( id ) != m_data.externalNames.end() ) return; + + m_data.externalNames.emplace( id, "???" ); + m_pendingExternalNames++; + + Query( ServerQueryExternalName, id ); +} + void Worker::AddSourceLocation( const QueueSourceLocation& srcloc ) { assert( m_pendingSourceLocation > 0 ); @@ -2575,6 +2602,16 @@ void Worker::AddCustomString( uint64_t ptr, char* str, size_t sz ) m_pendingCustomStrings.emplace( ptr, StoreString( str, sz ) ); } +void Worker::AddExternalName( uint64_t ptr, char* str, size_t sz ) +{ + assert( m_pendingExternalNames > 0 ); + m_pendingExternalNames--; + auto it = m_data.externalNames.find( ptr ); + assert( it != m_data.externalNames.end() && strcmp( it->second, "???" ) == 0 ); + const auto sl = StoreString( str, sz ); + it->second = sl.ptr; +} + static const uint8_t DxtcIndexTable[256] = { 85, 87, 86, 84, 93, 95, 94, 92, 89, 91, 90, 88, 81, 83, 82, 80, 117, 119, 118, 116, 125, 127, 126, 124, 121, 123, 122, 120, 113, 115, 114, 112, @@ -4063,6 +4100,12 @@ void Worker::ProcessContextSwitch( const QueueContextSwitch& ev ) auto& cx = cs.push_next(); cx.SetStart( time ); cx.SetThread( ev.newThread ); + + // At this point that check is approximate + if( !IsThreadLocal( ev.newThread ) ) + { + CheckExternalName( ev.newThread ); + } } } @@ -4886,8 +4929,6 @@ void Worker::Write( FileWrite& f ) WriteTimeOffset( f, refTime, cx.Start() ); WriteTimeOffset( f, refTime, cx.End() ); uint64_t thread = cx.Thread(); - // Don't care about external thread identifiers - if( m_data.threadMap.find( thread ) == m_data.threadMap.end() ) thread = 0; f.Write( &thread, sizeof( thread ) ); } } diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 530b190f..330fe8e8 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -173,6 +173,7 @@ private: Vector stringData; flat_hash_map stringMap; flat_hash_map> threadNames; + flat_hash_map> externalNames; flat_hash_map> sourceLocation; Vector sourceLocationPayload; @@ -334,6 +335,7 @@ public: const char* GetThreadString( uint64_t id ) const; bool IsThreadLocal( uint64_t id ) const; const SourceLocation& GetSourceLocation( int16_t srcloc ) const; + const char* GetExternalName( uint64_t id ) const; const char* GetZoneName( const SourceLocation& srcloc ) const; const char* GetZoneName( const ZoneEvent& ev ) const; @@ -477,6 +479,7 @@ private: void CheckString( uint64_t ptr ); void CheckThreadString( uint64_t id ); + void CheckExternalName( uint64_t id ); void AddSourceLocation( const QueueSourceLocation& srcloc ); void AddSourceLocationPayload( uint64_t ptr, char* data, size_t sz ); @@ -484,6 +487,7 @@ private: void AddString( uint64_t ptr, char* str, size_t sz ); void AddThreadString( uint64_t id, char* str, size_t sz ); void AddCustomString( uint64_t ptr, char* str, size_t sz ); + void AddExternalName( uint64_t ptr, char* str, size_t sz ); void AddFrameImageData( uint64_t ptr, char* data, size_t sz ); tracy_force_inline void AddCallstackPayload( uint64_t ptr, char* data, size_t sz ); @@ -560,6 +564,7 @@ private: uint32_t m_pendingStrings; uint32_t m_pendingThreads; + uint32_t m_pendingExternalNames; uint32_t m_pendingSourceLocation; uint32_t m_pendingCallstackFrames; uint8_t m_pendingCallstackSubframes;