mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-26 16:04:34 +00:00
Last-resort source code transfer from client to server.
This commit is contained in:
parent
3376620919
commit
ad2062fb40
@ -575,6 +575,12 @@ static void AckServerQuery()
|
|||||||
TracyLfqCommit;
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AckSourceCodeNotAvailable()
|
||||||
|
{
|
||||||
|
TracyLfqPrepare( QueueType::AckSourceCodeNotAvailable );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
static BroadcastMessage& GetBroadcastMessage( const char* procname, size_t pnsz, int& len, int port )
|
static BroadcastMessage& GetBroadcastMessage( const char* procname, size_t pnsz, int& len, int port )
|
||||||
{
|
{
|
||||||
static BroadcastMessage msg;
|
static BroadcastMessage msg;
|
||||||
@ -1143,6 +1149,7 @@ Profiler::Profiler()
|
|||||||
, m_deferredQueue( 64*1024 )
|
, m_deferredQueue( 64*1024 )
|
||||||
#endif
|
#endif
|
||||||
, m_paramCallback( nullptr )
|
, m_paramCallback( nullptr )
|
||||||
|
, m_queryData( nullptr )
|
||||||
{
|
{
|
||||||
assert( !s_instance );
|
assert( !s_instance );
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
@ -2426,7 +2433,8 @@ void Profiler::SendSecondString( const char* ptr, size_t len )
|
|||||||
void Profiler::SendLongString( uint64_t str, const char* ptr, size_t len, QueueType type )
|
void Profiler::SendLongString( uint64_t str, const char* ptr, size_t len, QueueType type )
|
||||||
{
|
{
|
||||||
assert( type == QueueType::FrameImageData ||
|
assert( type == QueueType::FrameImageData ||
|
||||||
type == QueueType::SymbolCode );
|
type == QueueType::SymbolCode ||
|
||||||
|
type == QueueType::SourceCode );
|
||||||
|
|
||||||
QueueItem item;
|
QueueItem item;
|
||||||
MemWrite( &item.hdr.type, type );
|
MemWrite( &item.hdr.type, type );
|
||||||
@ -2649,6 +2657,20 @@ bool Profiler::HandleServerQuery()
|
|||||||
case ServerQueryCodeLocation:
|
case ServerQueryCodeLocation:
|
||||||
SendCodeLocation( ptr );
|
SendCodeLocation( ptr );
|
||||||
break;
|
break;
|
||||||
|
case ServerQuerySourceCode:
|
||||||
|
HandleSourceCodeQuery();
|
||||||
|
break;
|
||||||
|
case ServerQueryDataTransfer:
|
||||||
|
assert( !m_queryData );
|
||||||
|
m_queryDataPtr = m_queryData = (char*)tracy_malloc( ptr + 11 );
|
||||||
|
AckServerQuery();
|
||||||
|
break;
|
||||||
|
case ServerQueryDataTransferPart:
|
||||||
|
memcpy( m_queryDataPtr, &ptr, 8 );
|
||||||
|
memcpy( m_queryDataPtr+8, &extra, 4 );
|
||||||
|
m_queryDataPtr += 12;
|
||||||
|
AckServerQuery();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert( false );
|
assert( false );
|
||||||
break;
|
break;
|
||||||
@ -3197,6 +3219,44 @@ void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size )
|
|||||||
SendLongString( symbol, (const char*)symbol, size, QueueType::SymbolCode );
|
SendLongString( symbol, (const char*)symbol, size, QueueType::SymbolCode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Profiler::HandleSourceCodeQuery()
|
||||||
|
{
|
||||||
|
assert( m_exectime != 0 );
|
||||||
|
assert( m_queryData );
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if( stat( m_queryData, &st ) == 0 && (uint64_t)st.st_mtime < m_exectime && st.st_size < ( TargetFrameSize - 16 ) )
|
||||||
|
{
|
||||||
|
FILE* f = fopen( m_queryData, "rb" );
|
||||||
|
tracy_free( m_queryData );
|
||||||
|
if( f )
|
||||||
|
{
|
||||||
|
auto ptr = (char*)tracy_malloc( st.st_size );
|
||||||
|
auto rd = fread( ptr, 1, st.st_size, f );
|
||||||
|
fclose( f );
|
||||||
|
if( rd == st.st_size )
|
||||||
|
{
|
||||||
|
SendLongString( (uint64_t)ptr, ptr, rd, QueueType::SourceCode );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AckSourceCodeNotAvailable();
|
||||||
|
}
|
||||||
|
tracy_free( ptr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AckSourceCodeNotAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tracy_free( m_queryData );
|
||||||
|
AckSourceCodeNotAvailable();
|
||||||
|
}
|
||||||
|
m_queryData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Profiler::SendCodeLocation( uint64_t ptr )
|
void Profiler::SendCodeLocation( uint64_t ptr )
|
||||||
{
|
{
|
||||||
#ifdef TRACY_HAS_CALLSTACK
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
@ -691,6 +691,7 @@ private:
|
|||||||
void HandleParameter( uint64_t payload );
|
void HandleParameter( uint64_t payload );
|
||||||
void HandleSymbolQuery( uint64_t symbol );
|
void HandleSymbolQuery( uint64_t symbol );
|
||||||
void HandleSymbolCodeQuery( uint64_t symbol, uint32_t size );
|
void HandleSymbolCodeQuery( uint64_t symbol, uint32_t size );
|
||||||
|
void HandleSourceCodeQuery();
|
||||||
|
|
||||||
void CalibrateTimer();
|
void CalibrateTimer();
|
||||||
void CalibrateDelay();
|
void CalibrateDelay();
|
||||||
@ -808,6 +809,9 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ParameterCallback m_paramCallback;
|
ParameterCallback m_paramCallback;
|
||||||
|
|
||||||
|
char* m_queryData;
|
||||||
|
char* m_queryDataPtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace tracy
|
|||||||
|
|
||||||
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
|
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
|
||||||
|
|
||||||
enum : uint32_t { ProtocolVersion = 45 };
|
enum : uint32_t { ProtocolVersion = 46 };
|
||||||
enum : uint16_t { BroadcastVersion = 2 };
|
enum : uint16_t { BroadcastVersion = 2 };
|
||||||
|
|
||||||
using lz4sz_t = uint32_t;
|
using lz4sz_t = uint32_t;
|
||||||
@ -51,7 +51,10 @@ enum ServerQuery : uint8_t
|
|||||||
ServerQueryParameter,
|
ServerQueryParameter,
|
||||||
ServerQuerySymbol,
|
ServerQuerySymbol,
|
||||||
ServerQuerySymbolCode,
|
ServerQuerySymbolCode,
|
||||||
ServerQueryCodeLocation
|
ServerQueryCodeLocation,
|
||||||
|
ServerQuerySourceCode,
|
||||||
|
ServerQueryDataTransfer,
|
||||||
|
ServerQueryDataTransferPart
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerQueryPacket
|
struct ServerQueryPacket
|
||||||
|
@ -85,6 +85,7 @@ enum class QueueType : uint8_t
|
|||||||
PlotConfig,
|
PlotConfig,
|
||||||
ParamSetup,
|
ParamSetup,
|
||||||
AckServerQueryNoop,
|
AckServerQueryNoop,
|
||||||
|
AckSourceCodeNotAvailable,
|
||||||
CpuTopology,
|
CpuTopology,
|
||||||
SingleStringData,
|
SingleStringData,
|
||||||
SecondStringData,
|
SecondStringData,
|
||||||
@ -100,6 +101,7 @@ enum class QueueType : uint8_t
|
|||||||
ExternalName,
|
ExternalName,
|
||||||
ExternalThreadName,
|
ExternalThreadName,
|
||||||
SymbolCode,
|
SymbolCode,
|
||||||
|
SourceCode,
|
||||||
NUM_TYPES
|
NUM_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -653,6 +655,7 @@ static constexpr size_t QueueDataSize[] = {
|
|||||||
sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),
|
sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),
|
||||||
sizeof( QueueHeader ) + sizeof( QueueParamSetup ),
|
sizeof( QueueHeader ) + sizeof( QueueParamSetup ),
|
||||||
sizeof( QueueHeader ), // server query acknowledgement
|
sizeof( QueueHeader ), // server query acknowledgement
|
||||||
|
sizeof( QueueHeader ), // source code not available
|
||||||
sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),
|
sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),
|
||||||
sizeof( QueueHeader ), // single string data
|
sizeof( QueueHeader ), // single string data
|
||||||
sizeof( QueueHeader ), // second string data
|
sizeof( QueueHeader ), // second string data
|
||||||
@ -669,6 +672,7 @@ static constexpr size_t QueueDataSize[] = {
|
|||||||
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name
|
||||||
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external thread name
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external thread name
|
||||||
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // symbol code
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // symbol code
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // source code
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" );
|
static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" );
|
||||||
|
@ -2860,7 +2860,8 @@ void Worker::Exec()
|
|||||||
m_data.plots.IsPending() || m_pendingCallstackId != 0 || m_pendingExternalNames != 0 ||
|
m_data.plots.IsPending() || m_pendingCallstackId != 0 || m_pendingExternalNames != 0 ||
|
||||||
m_pendingCallstackSubframes != 0 || m_pendingFrameImageData.image != nullptr || !m_pendingSymbols.empty() ||
|
m_pendingCallstackSubframes != 0 || m_pendingFrameImageData.image != nullptr || !m_pendingSymbols.empty() ||
|
||||||
!m_pendingSymbolCode.empty() || m_pendingCodeInformation != 0 || !m_serverQueryQueue.empty() ||
|
!m_pendingSymbolCode.empty() || m_pendingCodeInformation != 0 || !m_serverQueryQueue.empty() ||
|
||||||
m_pendingSourceLocationPayload != 0 || m_pendingSingleString.ptr != nullptr || m_pendingSecondString.ptr != nullptr )
|
m_pendingSourceLocationPayload != 0 || m_pendingSingleString.ptr != nullptr || m_pendingSecondString.ptr != nullptr ||
|
||||||
|
!m_sourceCodeQuery.empty() )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2993,9 +2994,13 @@ void Worker::DispatchFailure( const QueueItem& ev, const char*& ptr )
|
|||||||
{
|
{
|
||||||
ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );
|
ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );
|
||||||
if( ev.hdr.type == QueueType::FrameImageData ||
|
if( ev.hdr.type == QueueType::FrameImageData ||
|
||||||
ev.hdr.type == QueueType::SymbolCode )
|
ev.hdr.type == QueueType::SymbolCode ||
|
||||||
|
ev.hdr.type == QueueType::SourceCode )
|
||||||
{
|
{
|
||||||
if( ev.hdr.type == QueueType::SymbolCode ) m_serverQuerySpaceLeft++;
|
if( ev.hdr.type == QueueType::SymbolCode || ev.hdr.type == QueueType::SourceCode )
|
||||||
|
{
|
||||||
|
m_serverQuerySpaceLeft++;
|
||||||
|
}
|
||||||
uint32_t sz;
|
uint32_t sz;
|
||||||
memcpy( &sz, ptr, sizeof( sz ) );
|
memcpy( &sz, ptr, sizeof( sz ) );
|
||||||
ptr += sizeof( sz ) + sz;
|
ptr += sizeof( sz ) + sz;
|
||||||
@ -3063,6 +3068,7 @@ void Worker::DispatchFailure( const QueueItem& ev, const char*& ptr )
|
|||||||
case QueueType::SymbolInformation:
|
case QueueType::SymbolInformation:
|
||||||
case QueueType::CodeInformation:
|
case QueueType::CodeInformation:
|
||||||
case QueueType::AckServerQueryNoop:
|
case QueueType::AckServerQueryNoop:
|
||||||
|
case QueueType::AckSourceCodeNotAvailable:
|
||||||
m_serverQuerySpaceLeft++;
|
m_serverQuerySpaceLeft++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -3092,13 +3098,53 @@ void Worker::QueryTerminate()
|
|||||||
m_sock.Send( &query, ServerQueryPacketSize );
|
m_sock.Send( &query, ServerQueryPacketSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worker::QuerySourceFile( const char* fn )
|
||||||
|
{
|
||||||
|
QueryDataTransfer( fn, strlen( fn ) + 1 );
|
||||||
|
Query( ServerQuerySourceCode, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Worker::QueryDataTransfer( const void* ptr, size_t size )
|
||||||
|
{
|
||||||
|
Query( ServerQueryDataTransfer, size );
|
||||||
|
auto data = (const char*)ptr;
|
||||||
|
while( size > 0 )
|
||||||
|
{
|
||||||
|
uint64_t d8;
|
||||||
|
uint32_t d4;
|
||||||
|
if( size >= 12 )
|
||||||
|
{
|
||||||
|
memcpy( &d8, data, 8 );
|
||||||
|
memcpy( &d4, data+8, 4 );
|
||||||
|
data += 12;
|
||||||
|
size -= 12;
|
||||||
|
}
|
||||||
|
else if( size > 8 )
|
||||||
|
{
|
||||||
|
memcpy( &d8, data, 8 );
|
||||||
|
memset( &d4, 0, 4 );
|
||||||
|
memcpy( &d4, data+8, size-8 );
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset( &d8, 0, 8 );
|
||||||
|
memset( &d4, 0, 4 );
|
||||||
|
memcpy( &d8, data, size );
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
Query( ServerQueryDataTransferPart, d8, d4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )
|
bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )
|
||||||
{
|
{
|
||||||
if( ev.hdr.idx >= (int)QueueType::StringData )
|
if( ev.hdr.idx >= (int)QueueType::StringData )
|
||||||
{
|
{
|
||||||
ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );
|
ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );
|
||||||
if( ev.hdr.type == QueueType::FrameImageData ||
|
if( ev.hdr.type == QueueType::FrameImageData ||
|
||||||
ev.hdr.type == QueueType::SymbolCode )
|
ev.hdr.type == QueueType::SymbolCode ||
|
||||||
|
ev.hdr.type == QueueType::SourceCode )
|
||||||
{
|
{
|
||||||
uint32_t sz;
|
uint32_t sz;
|
||||||
memcpy( &sz, ptr, sizeof( sz ) );
|
memcpy( &sz, ptr, sizeof( sz ) );
|
||||||
@ -3112,6 +3158,10 @@ bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )
|
|||||||
AddSymbolCode( ev.stringTransfer.ptr, ptr, sz );
|
AddSymbolCode( ev.stringTransfer.ptr, ptr, sz );
|
||||||
m_serverQuerySpaceLeft++;
|
m_serverQuerySpaceLeft++;
|
||||||
break;
|
break;
|
||||||
|
case QueueType::SourceCode:
|
||||||
|
AddSourceCode( ptr, sz );
|
||||||
|
m_serverQuerySpaceLeft++;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert( false );
|
assert( false );
|
||||||
break;
|
break;
|
||||||
@ -3699,6 +3749,18 @@ void Worker::AddSymbolCode( uint64_t ptr, const char* data, size_t sz )
|
|||||||
cs_close( &handle );
|
cs_close( &handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Worker::AddSourceCode( const char* data, size_t sz )
|
||||||
|
{
|
||||||
|
assert( !m_sourceCodeQuery.empty() );
|
||||||
|
auto file = m_sourceCodeQuery.front();
|
||||||
|
m_sourceCodeQuery.erase( m_sourceCodeQuery.begin() );
|
||||||
|
if( m_data.sourceFileCache.find( file ) != m_data.sourceFileCache.end() ) return;
|
||||||
|
auto src = (char*)m_slab.AllocBig( sz );
|
||||||
|
memcpy( src, data, sz );
|
||||||
|
m_data.sourceFileCache.emplace( file, MemoryBlock{ src, uint32_t( sz ) } );
|
||||||
|
}
|
||||||
|
|
||||||
CallstackFrameId Worker::PackPointer( uint64_t ptr ) const
|
CallstackFrameId Worker::PackPointer( uint64_t ptr ) const
|
||||||
{
|
{
|
||||||
assert( ( ( ptr & 0x3000000000000000 ) << 2 ) == ( ptr & 0xC000000000000000 ) );
|
assert( ( ( ptr & 0x3000000000000000 ) << 2 ) == ( ptr & 0xC000000000000000 ) );
|
||||||
@ -4346,6 +4408,11 @@ bool Worker::Process( const QueueItem& ev )
|
|||||||
case QueueType::AckServerQueryNoop:
|
case QueueType::AckServerQueryNoop:
|
||||||
m_serverQuerySpaceLeft++;
|
m_serverQuerySpaceLeft++;
|
||||||
break;
|
break;
|
||||||
|
case QueueType::AckSourceCodeNotAvailable:
|
||||||
|
assert( !m_sourceCodeQuery.empty() );
|
||||||
|
m_sourceCodeQuery.erase( m_sourceCodeQuery.begin() );
|
||||||
|
m_serverQuerySpaceLeft++;
|
||||||
|
break;
|
||||||
case QueueType::CpuTopology:
|
case QueueType::CpuTopology:
|
||||||
ProcessCpuTopology( ev.cpuTopology );
|
ProcessCpuTopology( ev.cpuTopology );
|
||||||
break;
|
break;
|
||||||
@ -7430,6 +7497,11 @@ void Worker::CacheSource( const StringRef& str )
|
|||||||
fclose( f );
|
fclose( f );
|
||||||
m_data.sourceFileCache.emplace( file, MemoryBlock{ src, uint32_t( sz ) } );
|
m_data.sourceFileCache.emplace( file, MemoryBlock{ src, uint32_t( sz ) } );
|
||||||
}
|
}
|
||||||
|
else if( m_executableTime != 0 )
|
||||||
|
{
|
||||||
|
m_sourceCodeQuery.emplace_back( file );
|
||||||
|
QuerySourceFile( file );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Worker::GetSourceFileCacheSize() const
|
uint64_t Worker::GetSourceFileCacheSize() const
|
||||||
|
@ -595,6 +595,8 @@ private:
|
|||||||
void Exec();
|
void Exec();
|
||||||
void Query( ServerQuery type, uint64_t data, uint32_t extra = 0 );
|
void Query( ServerQuery type, uint64_t data, uint32_t extra = 0 );
|
||||||
void QueryTerminate();
|
void QueryTerminate();
|
||||||
|
void QuerySourceFile( const char* fn );
|
||||||
|
void QueryDataTransfer( const void* ptr, size_t size );
|
||||||
|
|
||||||
tracy_force_inline bool DispatchProcess( const QueueItem& ev, const char*& ptr );
|
tracy_force_inline bool DispatchProcess( const QueueItem& ev, const char*& ptr );
|
||||||
tracy_force_inline bool Process( const QueueItem& ev );
|
tracy_force_inline bool Process( const QueueItem& ev );
|
||||||
@ -752,6 +754,7 @@ private:
|
|||||||
void AddExternalThreadName( uint64_t ptr, const char* str, size_t sz );
|
void AddExternalThreadName( uint64_t ptr, const char* str, size_t sz );
|
||||||
void AddFrameImageData( uint64_t ptr, const char* data, size_t sz );
|
void AddFrameImageData( uint64_t ptr, const char* data, size_t sz );
|
||||||
void AddSymbolCode( uint64_t ptr, const char* data, size_t sz );
|
void AddSymbolCode( uint64_t ptr, const char* data, size_t sz );
|
||||||
|
void AddSourceCode( const char* data, size_t sz );
|
||||||
|
|
||||||
tracy_force_inline void AddCallstackPayload( uint64_t ptr, const char* data, size_t sz );
|
tracy_force_inline void AddCallstackPayload( uint64_t ptr, const char* data, size_t sz );
|
||||||
tracy_force_inline void AddCallstackAllocPayload( uint64_t ptr, const char* data, size_t sz );
|
tracy_force_inline void AddCallstackAllocPayload( uint64_t ptr, const char* data, size_t sz );
|
||||||
@ -945,6 +948,7 @@ private:
|
|||||||
size_t m_tmpBufSize = 0;
|
size_t m_tmpBufSize = 0;
|
||||||
|
|
||||||
unordered_flat_map<uint64_t, uint32_t> m_nextCallstack;
|
unordered_flat_map<uint64_t, uint32_t> m_nextCallstack;
|
||||||
|
std::vector<const char*> m_sourceCodeQuery;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user