[capture] Refactor: extract common functions

This commit is contained in:
Grégoire Roussel 2024-07-19 15:54:56 +02:00
parent 251715eda2
commit bcbe58b249

View File

@ -90,6 +90,152 @@ void AnsiPrintf( const char* ansiEscape, const char* format, ... ) {
}
}
// Check handshake status
// If failure, printf helpful message and return non-zero
int checkHandshake(tracy::HandshakeStatus handshake)
{
if( handshake == tracy::HandshakeProtocolMismatch )
{
printf( "\nThe client you are trying to connect to uses incompatible protocol version.\nMake sure you are using the same Tracy version on both client and server.\n" );
return 1;
}
if( handshake == tracy::HandshakeNotAvailable )
{
printf( "\nThe client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled.\n" );
return 2;
}
if( handshake == tracy::HandshakeDropped )
{
printf( "\nThe client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration.\n" );
return 3;
}
return 0;
}
void printWorkerUpdate(tracy::Worker& worker, int64_t memoryLimit)
{
auto& lock = worker.GetMbpsDataLock();
lock.lock();
const auto mbps = worker.GetMbpsData().back();
const auto compRatio = worker.GetCompRatio();
const auto netTotal = worker.GetDataTransferred();
lock.unlock();
const char* unit = "Mbps";
float unitsPerMbps = 1.f;
if( mbps < 0.1f )
{
unit = "Kbps";
unitsPerMbps = 1000.f;
}
AnsiPrintf( ANSI_ERASE_LINE, "\r");
AnsiPrintf( ANSI_CYAN ANSI_BOLD, "%7.2f %s", mbps * unitsPerMbps, unit );
printf( " /");
AnsiPrintf( ANSI_CYAN ANSI_BOLD, "%5.1f%%", compRatio * 100.f );
printf( " =");
AnsiPrintf( ANSI_YELLOW ANSI_BOLD, "%7.2f Mbps", mbps / compRatio );
printf( " | ");
AnsiPrintf( ANSI_YELLOW, "Tx: ");
AnsiPrintf( ANSI_GREEN, "%s", tracy::MemSizeToString( netTotal ) );
printf( " | ");
AnsiPrintf( ANSI_RED ANSI_BOLD, "%s", tracy::MemSizeToString( tracy::memUsage.load( std::memory_order_relaxed ) ) );
if( memoryLimit > 0 )
{
printf( " / " );
AnsiPrintf( ANSI_BLUE ANSI_BOLD, "%s", tracy::MemSizeToString( memoryLimit ) );
}
printf( " | ");
AnsiPrintf( ANSI_RED, "%s", tracy::TimeToString( worker.GetLastTime() - worker.GetFirstTime() ) );
fflush( stdout );
}
bool printWorkerFailure(tracy::Worker& worker)
{
auto const& failure = worker.GetFailureType();
if( failure == tracy::Worker::Failure::None )
{
return false;
}
else
{
AnsiPrintf( ANSI_RED ANSI_BOLD, "\nInstrumentation failure: %s", tracy::Worker::GetFailureString( failure ) );
auto& fd = worker.GetFailureData();
if( !fd.message.empty() )
{
printf( "\nContext: %s", fd.message.c_str() );
}
if( fd.callstack != 0 )
{
AnsiPrintf( ANSI_BOLD, "\nFailure callstack:\n" );
auto& cs = worker.GetCallstack( fd.callstack );
int fidx = 0;
for( auto& entry : cs )
{
auto frameData = worker.GetCallstackFrame( entry );
if( !frameData )
{
printf( "%3i. %p\n", fidx++, (void*)worker.GetCanonicalPointer( entry ) );
}
else
{
const auto fsz = frameData->size;
for( uint8_t f=0; f<fsz; f++ )
{
const auto& frame = frameData->data[f];
auto txt = worker.GetString( frame.name );
if( fidx == 0 && f != fsz-1 )
{
auto test = tracy::s_tracyStackFrames;
bool match = false;
do
{
if( strcmp( txt, *test ) == 0 )
{
match = true;
break;
}
}
while( *++test );
if( match ) continue;
}
if( f == fsz-1 )
{
printf( "%3i. ", fidx++ );
}
else
{
AnsiPrintf( ANSI_BLACK ANSI_BOLD, "inl. " );
}
AnsiPrintf( ANSI_CYAN, "%s ", txt );
txt = worker.GetString( frame.file );
if( frame.line == 0 )
{
AnsiPrintf( ANSI_YELLOW, "(%s)", txt );
}
else
{
AnsiPrintf( ANSI_YELLOW, "(%s:%" PRIu32 ")", txt, frame.line );
}
if( frameData->imageName.Active() )
{
AnsiPrintf( ANSI_MAGENTA, " %s\n", worker.GetString( frameData->imageName ) );
}
else
{
printf( "\n" );
}
}
}
}
}
return true;
}
}
[[noreturn]] void Usage()
{
printf( "Usage: capture -o output.tracy [-a address] [-p port] [-f] [-s seconds] [-m memlimit]\n" );
@ -167,22 +313,13 @@ int main( int argc, char** argv )
tracy::Worker worker( address, port, memoryLimit );
while( !worker.HasData() )
{
const auto handshake = worker.GetHandshakeStatus();
if( handshake == tracy::HandshakeProtocolMismatch )
const auto handshake = static_cast<tracy::HandshakeStatus>(worker.GetHandshakeStatus());
int status = checkHandshake(handshake);
if (status != 0)
{
printf( "\nThe client you are trying to connect to uses incompatible protocol version.\nMake sure you are using the same Tracy version on both client and server.\n" );
return 1;
}
if( handshake == tracy::HandshakeNotAvailable )
{
printf( "\nThe client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled.\n" );
return 2;
}
if( handshake == tracy::HandshakeDropped )
{
printf( "\nThe client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration.\n" );
return 3;
return status;
}
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
}
printf( "\nQueue delay: %s\nTimer resolution: %s\n", tracy::TimeToString( worker.GetDelay() ), tracy::TimeToString( worker.GetResolution() ) );
@ -196,9 +333,6 @@ int main( int argc, char** argv )
sigaction( SIGINT, &sigint, &oldsigint );
#endif
const auto firstTime = worker.GetFirstTime();
auto& lock = worker.GetMbpsDataLock();
const auto t0 = std::chrono::high_resolution_clock::now();
while( worker.IsConnected() )
{
@ -213,42 +347,11 @@ int main( int argc, char** argv )
s_disconnect.store(false, std::memory_order_relaxed );
break;
}
lock.lock();
const auto mbps = worker.GetMbpsData().back();
const auto compRatio = worker.GetCompRatio();
const auto netTotal = worker.GetDataTransferred();
lock.unlock();
// Output progress info only if destination is a TTY to avoid bloating
// log files (so this is not just about usage of ANSI color codes).
if( IsStdoutATerminal() )
{
const char* unit = "Mbps";
float unitsPerMbps = 1.f;
if( mbps < 0.1f )
{
unit = "Kbps";
unitsPerMbps = 1000.f;
}
AnsiPrintf( ANSI_ERASE_LINE ANSI_CYAN ANSI_BOLD, "\r%7.2f %s", mbps * unitsPerMbps, unit );
printf( " /");
AnsiPrintf( ANSI_CYAN ANSI_BOLD, "%5.1f%%", compRatio * 100.f );
printf( " =");
AnsiPrintf( ANSI_YELLOW ANSI_BOLD, "%7.2f Mbps", mbps / compRatio );
printf( " | ");
AnsiPrintf( ANSI_YELLOW, "Tx: ");
AnsiPrintf( ANSI_GREEN, "%s", tracy::MemSizeToString( netTotal ) );
printf( " | ");
AnsiPrintf( ANSI_RED ANSI_BOLD, "%s", tracy::MemSizeToString( tracy::memUsage.load( std::memory_order_relaxed ) ) );
if( memoryLimit > 0 )
{
printf( " / " );
AnsiPrintf( ANSI_BLUE ANSI_BOLD, "%s", tracy::MemSizeToString( memoryLimit ) );
}
printf( " | ");
AnsiPrintf( ANSI_RED, "%s", tracy::TimeToString( worker.GetLastTime() - firstTime ) );
fflush( stdout );
printWorkerUpdate(worker, memoryLimit);
}
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
@ -265,85 +368,10 @@ int main( int argc, char** argv )
}
const auto t1 = std::chrono::high_resolution_clock::now();
const auto& failure = worker.GetFailureType();
if( failure != tracy::Worker::Failure::None )
{
AnsiPrintf( ANSI_RED ANSI_BOLD, "\nInstrumentation failure: %s", tracy::Worker::GetFailureString( failure ) );
auto& fd = worker.GetFailureData();
if( !fd.message.empty() )
{
printf( "\nContext: %s", fd.message.c_str() );
}
if( fd.callstack != 0 )
{
AnsiPrintf( ANSI_BOLD, "\nFailure callstack:\n" );
auto& cs = worker.GetCallstack( fd.callstack );
int fidx = 0;
for( auto& entry : cs )
{
auto frameData = worker.GetCallstackFrame( entry );
if( !frameData )
{
printf( "%3i. %p\n", fidx++, (void*)worker.GetCanonicalPointer( entry ) );
}
else
{
const auto fsz = frameData->size;
for( uint8_t f=0; f<fsz; f++ )
{
const auto& frame = frameData->data[f];
auto txt = worker.GetString( frame.name );
if( fidx == 0 && f != fsz-1 )
{
auto test = tracy::s_tracyStackFrames;
bool match = false;
do
{
if( strcmp( txt, *test ) == 0 )
{
match = true;
break;
}
}
while( *++test );
if( match ) continue;
}
if( f == fsz-1 )
{
printf( "%3i. ", fidx++ );
}
else
{
AnsiPrintf( ANSI_BLACK ANSI_BOLD, "inl. " );
}
AnsiPrintf( ANSI_CYAN, "%s ", txt );
txt = worker.GetString( frame.file );
if( frame.line == 0 )
{
AnsiPrintf( ANSI_YELLOW, "(%s)", txt );
}
else
{
AnsiPrintf( ANSI_YELLOW, "(%s:%" PRIu32 ")", txt, frame.line );
}
if( frameData->imageName.Active() )
{
AnsiPrintf( ANSI_MAGENTA, " %s\n", worker.GetString( frameData->imageName ) );
}
else
{
printf( "\n" );
}
}
}
}
}
}
printWorkerFailure(worker);
printf( "\nFrames: %" PRIu64 "\nTime span: %s\nZones: %s\nElapsed time: %s\nSaving trace...",
worker.GetFrameCount( *worker.GetFramesBase() ), tracy::TimeToString( worker.GetLastTime() - firstTime ), tracy::RealToString( worker.GetZoneCount() ),
worker.GetFrameCount( *worker.GetFramesBase() ), tracy::TimeToString( worker.GetLastTime() - worker.GetFirstTime() ), tracy::RealToString( worker.GetZoneCount() ),
tracy::TimeToString( std::chrono::duration_cast<std::chrono::nanoseconds>( t1 - t0 ).count() ) );
fflush( stdout );
auto f = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output, tracy::FileCompression::Zstd, 3, 4 ) );