2018-03-10 00:29:27 +00:00
# ifdef _WIN32
# include <windows.h>
# endif
# include <chrono>
2018-03-10 01:25:29 +00:00
# include <inttypes.h>
2018-03-10 00:29:27 +00:00
# include <mutex>
2018-03-10 01:25:29 +00:00
# include <stdint.h>
2018-03-10 00:29:27 +00:00
# include <stdio.h>
# include <stdlib.h>
2018-09-09 17:28:53 +00:00
# include "../../common/TracyProtocol.hpp"
2018-03-10 00:29:27 +00:00
# include "../../server/TracyFileWrite.hpp"
# include "../../server/TracyMemory.hpp"
# include "../../server/TracyWorker.hpp"
# include "getopt.h"
2018-03-10 01:25:29 +00:00
static const char * TimeToString ( int64_t ns )
{
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
const char * sign = " " ;
if ( ns < 0 )
{
sign = " - " ;
ns = - ns ;
}
if ( ns < 1000 )
{
sprintf ( buf , " %s% " PRIi64 " ns " , sign , ns ) ;
}
else if ( ns < 1000ll * 1000 )
{
sprintf ( buf , " %s%.2f us " , sign , ns / 1000. ) ;
}
else if ( ns < 1000ll * 1000 * 1000 )
{
sprintf ( buf , " %s%.2f ms " , sign , ns / ( 1000. * 1000. ) ) ;
}
else if ( ns < 1000ll * 1000 * 1000 * 60 )
{
sprintf ( buf , " %s%.2f s " , sign , ns / ( 1000. * 1000. * 1000. ) ) ;
}
else
{
const auto m = int64_t ( ns / ( 1000ll * 1000 * 1000 * 60 ) ) ;
const auto s = int64_t ( ns - m * ( 1000ll * 1000 * 1000 * 60 ) ) ;
sprintf ( buf , " %s% " PRIi64 " :%04.1f " , sign , m , s / ( 1000. * 1000. * 1000. ) ) ;
}
return buf ;
}
static const char * RealToString ( double val , bool separator )
{
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
sprintf ( buf , " %f " , val ) ;
auto ptr = buf ;
if ( * ptr = = ' - ' ) ptr + + ;
const auto vbegin = ptr ;
if ( separator )
{
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
auto end = ptr ;
while ( * end ! = ' \0 ' ) end + + ;
auto sz = end - ptr ;
while ( ptr - vbegin > 3 )
{
ptr - = 3 ;
memmove ( ptr + 1 , ptr , sz ) ;
* ptr = ' , ' ;
sz + = 4 ;
}
}
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
if ( * ptr = = ' \0 ' ) return buf ;
while ( * ptr ! = ' \0 ' ) ptr + + ;
ptr - - ;
while ( * ptr = = ' 0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr - - ;
if ( * ptr ! = ' . ' & & * ptr ! = ' , ' ) ptr + + ;
* ptr = ' \0 ' ;
return buf ;
}
2018-03-10 00:29:27 +00:00
void Usage ( )
{
printf ( " Usage: capture -a address -o output.tracy \n " ) ;
exit ( 1 ) ;
}
int main ( int argc , char * * argv )
{
# ifdef _WIN32
if ( ! AttachConsole ( ATTACH_PARENT_PROCESS ) )
{
AllocConsole ( ) ;
SetConsoleMode ( GetStdHandle ( STD_OUTPUT_HANDLE ) , 0x07 ) ;
}
# endif
const char * address = nullptr ;
const char * output = nullptr ;
int c ;
while ( ( c = getopt ( argc , argv , " a:o: " ) ) ! = - 1 )
{
switch ( c )
{
case ' a ' :
address = optarg ;
break ;
case ' o ' :
output = optarg ;
break ;
default :
Usage ( ) ;
break ;
}
}
if ( ! address | | ! output ) Usage ( ) ;
printf ( " Connecting to %s... " , address ) ;
fflush ( stdout ) ;
tracy : : Worker worker ( address ) ;
2018-09-09 17:28:53 +00:00
for ( ; ; )
{
const auto handshake = worker . GetHandshakeStatus ( ) ;
if ( handshake = = tracy : : HandshakeWelcome ) break ;
if ( handshake = = tracy : : HandshakeProtocolMismatch )
{
printf ( " \n The client you are trying to connect to uses incompatible protocol version. \n Make sure you are using the same Tracy version on both client and server. \n " ) ;
return 1 ;
}
2018-09-09 17:42:06 +00:00
if ( handshake = = tracy : : HandshakeNotAvailable )
{
printf ( " \n The client you are trying to connect to is no longer able to sent profiling data, \n because another server was already connected to it. \n You 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 ;
}
2018-09-09 17:28:53 +00:00
}
2018-03-10 00:29:27 +00:00
while ( ! worker . HasData ( ) ) std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 100 ) ) ;
2018-03-10 01:25:29 +00:00
printf ( " \n Queue delay: %s \n Timer resolution: %s \n " , TimeToString ( worker . GetDelay ( ) ) , TimeToString ( worker . GetResolution ( ) ) ) ;
2018-03-10 00:29:27 +00:00
auto & lock = worker . GetMbpsDataLock ( ) ;
while ( worker . IsConnected ( ) )
{
lock . lock ( ) ;
const auto mbps = worker . GetMbpsData ( ) . back ( ) ;
const auto compRatio = worker . GetCompRatio ( ) ;
lock . unlock ( ) ;
if ( mbps < 0.1f )
{
printf ( " \33 [2K \r \033 [36;1m%7.2f Kbps " , mbps * 1000.f ) ;
}
else
{
printf ( " \33 [2K \r \033 [36;1m%7.2f Mbps " , mbps ) ;
}
2018-09-18 14:24:32 +00:00
printf ( " \033 [0m / \033 [36;1m%5.1f%% \033 [0m= \033 [33;1m%7.2f Mbps \033 [0m| Mem: \033 [31;1m%.2f MB \033 [0m | \033 [33mTime: %s \033 [0m " , compRatio * 100.f , mbps / compRatio , tracy : : memUsage . load ( std : : memory_order_relaxed ) / ( 1024.f * 1024.f ) , TimeToString ( worker . GetLastTime ( ) - worker . GetTimeBegin ( ) ) ) ;
2018-03-10 00:29:27 +00:00
fflush ( stdout ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 100 ) ) ;
}
2018-08-04 21:53:21 +00:00
printf ( " \n Frames: % " PRIu64 " \n Time span: %s \n Zones: %s \n Saving trace... " , worker . GetFrameCount ( * worker . GetFramesBase ( ) ) , TimeToString ( worker . GetLastTime ( ) - worker . GetTimeBegin ( ) ) , RealToString ( worker . GetZoneCount ( ) , true ) ) ;
2018-03-10 00:29:27 +00:00
fflush ( stdout ) ;
2018-03-28 23:11:54 +00:00
auto f = std : : unique_ptr < tracy : : FileWrite > ( tracy : : FileWrite : : Open ( output ) ) ;
2018-03-10 00:29:27 +00:00
if ( f )
{
worker . Write ( * f ) ;
printf ( " \033 [32;1mdone! \033 [0m \n " ) ;
}
else
{
printf ( " \033 [31;1failed! \033 [0m \n " ) ;
}
return 0 ;
}