From 7424077d703d438746e12077bbcf3dbe64f12e8b Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 26 Sep 2017 02:28:14 +0200 Subject: [PATCH] Store source location in a single object. Source file, function name and line number are now stored in a const static container object. This has the following benefits: - Slightly lighter profiling workload (3 instructions less). - Profiling queue event size is significantly reduced, by 12 bytes. This has an effect on all queue event types. - Source location grouping has now no cost, as it's performed at the compilation stage. This allows simplification of server code. The downside is that the full source location resolution is now performed in two steps, as the server has to query both source location container and strings contained within. This has almost no real impact on profiler operation. --- client/Tracy.hpp | 4 +-- client/TracyProfiler.cpp | 35 +++++++++++++++++--- client/TracyProfiler.hpp | 8 +++++ client/TracyScoped.hpp | 4 +-- common/TracyProtocol.hpp | 3 +- common/TracyQueue.hpp | 14 ++++++-- server/TracyEvent.hpp | 2 +- server/TracySourceLocation.hpp | 37 --------------------- server/TracyView.cpp | 60 +++++++++++++++++++++++----------- server/TracyView.hpp | 8 +++-- 10 files changed, 103 insertions(+), 72 deletions(-) delete mode 100755 server/TracySourceLocation.hpp diff --git a/client/Tracy.hpp b/client/Tracy.hpp index 653fa619..7b6eacc3 100755 --- a/client/Tracy.hpp +++ b/client/Tracy.hpp @@ -13,8 +13,8 @@ #include "TracyProfiler.hpp" #include "TracyScoped.hpp" -#define ZoneScoped tracy::ScopedZone ___tracy_scoped_zone( __FILE__, __FUNCTION__, __LINE__, 0 ); -#define ZoneScopedC( color ) tracy::ScopedZone ___tracy_scoped_zone( __FILE__, __FUNCTION__, __LINE__, color ); +#define ZoneScoped static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, __LINE__ }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, 0 ); +#define ZoneScopedC( color ) static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, __LINE__ }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, color ); #define FrameMark tracy::Profiler::FrameMark(); diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index bd62810d..b222743c 100755 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -216,6 +216,27 @@ bool Profiler::SendString( uint64_t str, const char* ptr, QueueType type ) return SendData( buf, sizeof( hdr ) + sizeof( l16 ) + l16 ); } +bool Profiler::SendSourceLocation( uint64_t ptr ) +{ + auto srcloc = (const SourceLocation*)ptr; + QueueItem item; + item.hdr.type = QueueType::SourceLocation; + item.hdr.id = ptr; + item.srcloc.file = (uint64_t)srcloc->file; + item.srcloc.function = (uint64_t)srcloc->function; + item.srcloc.line = srcloc->line; + + const auto sz = QueueDataSize[item.hdr.idx]; + + auto buf = m_buffer + m_bufferOffset; + memcpy( buf, &item, sz ); + + m_bufferOffset += sz; + if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0; + + return SendData( buf, sz ); +} + bool Profiler::HandleServerQuery() { timeval tv; @@ -243,6 +264,9 @@ bool Profiler::HandleServerQuery() SendString( ptr, GetThreadName( ptr ), QueueType::ThreadName ); } break; + case ServerQuerySourceLocation: + SendSourceLocation( ptr ); + break; default: assert( false ); break; @@ -277,7 +301,7 @@ void Profiler::CalibrateTimer() class FakeZone { public: - FakeZone( const char* file, const char* function, uint32_t line, uint32_t color ) {} + FakeZone( const SourceLocation* srcloc, uint32_t color ) {} ~FakeZone() {} private: @@ -291,17 +315,20 @@ void Profiler::CalibrateDelay() static_assert( Events * 2 < QueuePrealloc, "Delay calibration loop will allocate memory in queue" ); for( int i=0; i= 64 * 1024, "Not enough space for LZ4 strea enum ServerQuery : uint8_t { ServerQueryString, - ServerQueryThreadString + ServerQueryThreadString, + ServerQuerySourceLocation }; #pragma pack( 1 ) diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 5224e266..d7bf1758 100755 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -13,6 +13,7 @@ enum class QueueType : uint8_t StringData, ThreadName, FrameMark, + SourceLocation, NUM_TYPES }; @@ -21,9 +22,7 @@ enum class QueueType : uint8_t struct QueueZoneBegin { int64_t time; - uint64_t filename; // ptr - uint64_t function; // ptr - uint32_t line; + uint64_t srcloc; // ptr uint64_t thread; uint32_t color; }; @@ -33,6 +32,13 @@ struct QueueZoneEnd int64_t time; }; +struct QueueSourceLocation +{ + uint64_t function; // ptr + uint64_t file; // ptr + uint32_t line; +}; + struct QueueHeader { union @@ -50,6 +56,7 @@ struct QueueItem { QueueZoneBegin zoneBegin; QueueZoneEnd zoneEnd; + QueueSourceLocation srcloc; }; }; @@ -63,6 +70,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ), sizeof( QueueHeader ), sizeof( QueueHeader ), + sizeof( QueueHeader ) + sizeof( QueueSourceLocation ), }; static_assert( sizeof( QueueDataSize ) / sizeof( size_t ) == (uint8_t)QueueType::NUM_TYPES, "QueueDataSize mismatch" ); diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index b5189371..283e3e17 100755 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -10,7 +10,7 @@ struct Event { int64_t start; int64_t end; - uint32_t srcloc; + uint64_t srcloc; uint32_t color; Event* parent; diff --git a/server/TracySourceLocation.hpp b/server/TracySourceLocation.hpp deleted file mode 100755 index a583b9fc..00000000 --- a/server/TracySourceLocation.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __TRACYSOURCELOCATION_HPP__ -#define __TRACYSOURCELOCATION_HPP__ - -#include -#include -#include - -namespace tracy -{ - -struct SourceLocation -{ - uint64_t filename; - uint64_t function; - uint32_t line; - - struct Hasher - { - size_t operator()( const SourceLocation& v ) const - { - const static std::hash hash; - return hash( v.filename ) ^ hash( v.function ) ^ hash( v.line ); - } - }; - - struct Comparator - { - bool operator()( const SourceLocation& lhs, const SourceLocation& rhs ) const - { - return memcmp( &lhs, &rhs, sizeof( SourceLocation ) ) == 0; - } - }; -}; - -} - -#endif diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 1a13f8cb..de922bf0 100755 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -219,6 +219,9 @@ void View::Process( const QueueItem& ev ) case QueueType::FrameMark: ProcessFrameMark( ev.hdr.id ); break; + case QueueType::SourceLocation: + AddSourceLocation( ev.hdr.id, ev.srcloc ); + break; default: assert( false ); break; @@ -230,27 +233,14 @@ void View::ProcessZoneBegin( uint64_t id, const QueueZoneBegin& ev ) auto it = m_pendingEndZone.find( id ); auto zone = m_slab.Alloc(); - CheckString( ev.filename ); - CheckString( ev.function ); + CheckSourceLocation( ev.srcloc ); CheckThreadString( ev.thread ); + zone->start = ev.time * m_timerMul; + zone->srcloc = ev.srcloc; zone->color = ev.color; - SourceLocation srcloc { ev.filename, ev.function, ev.line }; - auto lit = m_locationRef.find( srcloc ); - std::unique_lock lock( m_lock ); - if( lit == m_locationRef.end() ) - { - const auto ref = uint32_t( m_srcFile.size() ); - zone->srcloc = ref; - m_locationRef.emplace( srcloc, ref ); - m_srcFile.push_back( srcloc ); - } - else - { - zone->srcloc = lit->second; - } if( it == m_pendingEndZone.end() ) { @@ -331,6 +321,18 @@ void View::CheckThreadString( uint64_t id ) m_sock.Send( &id, sizeof( id ) ); } +void View::CheckSourceLocation( uint64_t ptr ) +{ + if( m_sourceLocation.find( ptr ) != m_sourceLocation.end() ) return; + if( m_pendingSourceLocation.find( ptr ) != m_pendingSourceLocation.end() ) return; + + m_pendingSourceLocation.emplace( ptr ); + + uint8_t type = ServerQuerySourceLocation; + m_sock.Send( &type, sizeof( type ) ); + m_sock.Send( &ptr, sizeof( ptr ) ); +} + void View::AddString( uint64_t ptr, std::string&& str ) { assert( m_strings.find( ptr ) == m_strings.end() ); @@ -351,6 +353,17 @@ void View::AddThreadString( uint64_t id, std::string&& str ) m_threadNames.emplace( id, std::move( str ) ); } +void View::AddSourceLocation( uint64_t ptr, const QueueSourceLocation& srcloc ) +{ + assert( m_sourceLocation.find( ptr ) == m_sourceLocation.end() ); + auto it = m_pendingSourceLocation.find( ptr ); + assert( it != m_pendingSourceLocation.end() ); + m_pendingSourceLocation.erase( it ); + CheckString( srcloc.file ); + CheckString( srcloc.function ); + std::lock_guard lock( m_lock ); + m_sourceLocation.emplace( ptr, srcloc ); +} void View::NewZone( Event* zone, uint64_t thread ) { @@ -1043,8 +1056,17 @@ int View::DrawZoneLevel( const Vector& vec, bool hover, double pxns, con } else { - const auto& srcFile = m_srcFile[ev.srcloc]; - const char* func = GetString( srcFile.function ); + const char* func = "???"; + const char* filename = "???"; + uint32_t line = 0; + auto srcit = m_sourceLocation.find( ev.srcloc ); + if( srcit != m_sourceLocation.end() ) + { + func = GetString( srcit->second.function ); + filename = GetString( srcit->second.file ); + line = srcit->second.line; + } + const auto tsz = ImGui::CalcTextSize( func ); const auto pr0 = ( ev.start - m_zvStart ) * pxns; const auto pr1 = ( end - m_zvStart ) * pxns; @@ -1082,7 +1104,7 @@ int View::DrawZoneLevel( const Vector& vec, bool hover, double pxns, con { ImGui::BeginTooltip(); ImGui::Text( "%s", func ); - ImGui::Text( "%s:%i", GetString( srcFile.filename ), srcFile.line ); + ImGui::Text( "%s:%i", filename, line ); ImGui::Text( "Execution time: %s", TimeToString( end - ev.start ) ); ImGui::Text( "Without profiling: %s", TimeToString( end - ev.start - m_delay ) ); ImGui::EndTooltip(); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index df54a503..21c31717 100755 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -14,7 +14,6 @@ #include "../common/TracyQueue.hpp" #include "TracyEvent.hpp" #include "TracySlab.hpp" -#include "TracySourceLocation.hpp" #include "TracyVector.hpp" struct ImVec2; @@ -53,8 +52,11 @@ private: void CheckString( uint64_t ptr ); void CheckThreadString( uint64_t id ); + void CheckSourceLocation( uint64_t ptr ); + void AddString( uint64_t ptr, std::string&& str ); void AddThreadString( uint64_t id, std::string&& str ); + void AddSourceLocation( uint64_t id, const QueueSourceLocation& srcloc ); void NewZone( Event* zone, uint64_t thread ); void UpdateZone( Event* zone ); @@ -87,10 +89,10 @@ private: // this block must be locked std::mutex m_lock; Vector m_frames; - Vector m_srcFile; Vector m_threads; std::unordered_map m_strings; std::unordered_map m_threadNames; + std::unordered_map m_sourceLocation; uint64_t m_zonesCnt; std::mutex m_mbpslock; @@ -101,7 +103,7 @@ private: std::unordered_map m_openZones; std::unordered_set m_pendingStrings; std::unordered_set m_pendingThreads; - std::unordered_map m_locationRef; + std::unordered_set m_pendingSourceLocation; std::unordered_map m_threadMap; Slab m_slab;