tracy/server/TracyWorker.cpp

5877 lines
182 KiB
C++
Raw Normal View History

2019-06-22 11:40:00 +00:00
#ifdef _MSC_VER
# pragma warning( disable: 4244 4267 ) // conversion from don't care to whatever, possible loss of data
#endif
2019-01-19 11:03:30 +00:00
#ifdef _WIN32
2018-12-18 15:52:05 +00:00
# include <malloc.h>
#else
# include <alloca.h>
#endif
#include <cctype>
#include <chrono>
#include <string.h>
#include <inttypes.h>
#if ( defined _MSC_VER && _MSVC_LANG >= 201703L ) || __cplusplus >= 201703L
2018-07-17 16:10:49 +00:00
# if __has_include(<execution>)
# include <execution>
# else
# define MY_LIBCPP_SUCKS
# endif
#else
# define MY_LIBCPP_SUCKS
#endif
2018-07-17 16:29:07 +00:00
#ifdef MY_LIBCPP_SUCKS
2018-07-17 16:10:49 +00:00
# include "tracy_pdqsort.h"
#endif
#include "../common/TracyProtocol.hpp"
#include "../common/TracySystem.hpp"
#include "TracyFileRead.hpp"
#include "TracyFileWrite.hpp"
2019-09-20 21:03:12 +00:00
#include "TracyTaskDispatch.hpp"
#include "TracyVersion.hpp"
#include "TracyWorker.hpp"
#include "tracy_flat_hash_map.hpp"
namespace tracy
{
static inline CallstackFrameId PackPointer( uint64_t ptr )
{
assert( ( ( ptr & 0x4000000000000000 ) << 1 ) == ( ptr & 0x8000000000000000 ) );
CallstackFrameId id;
id.idx = ptr;
id.sel = 0;
return id;
}
static const uint8_t FileHeader[8] { 't', 'r', 'a', 'c', 'y', Version::Major, Version::Minor, Version::Patch };
enum { FileHeaderMagic = 5 };
static const int CurrentVersion = FileVersion( Version::Major, Version::Minor, Version::Patch );
2019-11-21 20:48:35 +00:00
static const int MinSupportedVersion = FileVersion( 0, 5, 0 );
static void UpdateLockCountLockable( LockMap& lockmap, size_t pos )
{
auto& timeline = lockmap.timeline;
2019-05-12 14:17:17 +00:00
bool isContended = lockmap.isContended;
uint8_t lockingThread;
uint8_t lockCount;
uint64_t waitList;
if( pos == 0 )
{
lockingThread = 0;
lockCount = 0;
waitList = 0;
}
else
{
const auto& tl = timeline[pos-1];
lockingThread = tl.lockingThread;
lockCount = tl.lockCount;
waitList = tl.waitList;
}
const auto end = timeline.size();
while( pos != end )
{
auto& tl = timeline[pos];
const auto tbit = uint64_t( 1 ) << tl.ptr->thread;
switch( (LockEvent::Type)tl.ptr->type )
{
case LockEvent::Type::Wait:
waitList |= tbit;
break;
case LockEvent::Type::Obtain:
assert( lockCount < std::numeric_limits<uint8_t>::max() );
assert( ( waitList & tbit ) != 0 );
waitList &= ~tbit;
lockingThread = tl.ptr->thread;
lockCount++;
break;
case LockEvent::Type::Release:
assert( lockCount > 0 );
lockCount--;
break;
default:
break;
}
tl.lockingThread = lockingThread;
tl.waitList = waitList;
tl.lockCount = lockCount;
2019-05-12 14:17:17 +00:00
if( !isContended ) isContended = lockCount != 0 && waitList != 0;
pos++;
}
2019-05-12 14:17:17 +00:00
lockmap.isContended = isContended;
}
static void UpdateLockCountSharedLockable( LockMap& lockmap, size_t pos )
{
auto& timeline = lockmap.timeline;
2019-05-12 14:17:17 +00:00
bool isContended = lockmap.isContended;
uint8_t lockingThread;
uint8_t lockCount;
uint64_t waitShared;
uint64_t waitList;
uint64_t sharedList;
if( pos == 0 )
{
lockingThread = 0;
lockCount = 0;
waitShared = 0;
waitList = 0;
sharedList = 0;
}
else
{
const auto& tl = timeline[pos-1];
2019-11-02 14:40:06 +00:00
const auto tlp = (const LockEventShared*)(const LockEvent*)tl.ptr;
lockingThread = tl.lockingThread;
lockCount = tl.lockCount;
waitShared = tlp->waitShared;
waitList = tl.waitList;
sharedList = tlp->sharedList;
}
const auto end = timeline.size();
// ObtainShared and ReleaseShared should assert on lockCount == 0, but
2019-05-12 13:59:53 +00:00
// due to the async retrieval of data from threads that's not possible.
while( pos != end )
{
auto& tl = timeline[pos];
2019-11-02 14:40:06 +00:00
const auto tlp = (LockEventShared*)(LockEvent*)tl.ptr;
const auto tbit = uint64_t( 1 ) << tlp->thread;
switch( (LockEvent::Type)tlp->type )
{
case LockEvent::Type::Wait:
waitList |= tbit;
break;
case LockEvent::Type::WaitShared:
waitShared |= tbit;
break;
case LockEvent::Type::Obtain:
assert( lockCount < std::numeric_limits<uint8_t>::max() );
assert( ( waitList & tbit ) != 0 );
waitList &= ~tbit;
lockingThread = tlp->thread;
lockCount++;
break;
case LockEvent::Type::Release:
assert( lockCount > 0 );
lockCount--;
break;
case LockEvent::Type::ObtainShared:
assert( ( waitShared & tbit ) != 0 );
assert( ( sharedList & tbit ) == 0 );
waitShared &= ~tbit;
sharedList |= tbit;
break;
case LockEvent::Type::ReleaseShared:
assert( ( sharedList & tbit ) != 0 );
sharedList &= ~tbit;
break;
default:
break;
}
tl.lockingThread = lockingThread;
tlp->waitShared = waitShared;
tl.waitList = waitList;
tlp->sharedList = sharedList;
tl.lockCount = lockCount;
2019-05-12 14:17:17 +00:00
if( !isContended ) isContended = ( lockCount != 0 && ( waitList != 0 || waitShared != 0 ) ) || ( sharedList != 0 && waitList != 0 );
pos++;
}
2019-05-12 14:17:17 +00:00
lockmap.isContended = isContended;
}
static inline void UpdateLockCount( LockMap& lockmap, size_t pos )
{
if( lockmap.type == LockType::Lockable )
{
UpdateLockCountLockable( lockmap, pos );
}
else
{
UpdateLockCountSharedLockable( lockmap, pos );
}
}
static tracy_force_inline void WriteTimeOffset( FileWrite& f, int64_t& refTime, int64_t time )
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
{
int64_t timeOffset = time - refTime;
refTime += timeOffset;
f.Write( &timeOffset, sizeof( timeOffset ) );
}
static tracy_force_inline int64_t ReadTimeOffset( FileRead& f, int64_t& refTime )
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
{
int64_t timeOffset;
f.Read( timeOffset );
refTime += timeOffset;
return refTime;
}
static tracy_force_inline void UpdateLockRange( LockMap& lockmap, const LockEvent& ev, int64_t lt )
2019-03-16 01:28:32 +00:00
{
auto& range = lockmap.range[ev.thread];
if( range.start > lt ) range.start = lt;
if( range.end < lt ) range.end = lt;
}
2018-07-28 15:59:17 +00:00
LoadProgress Worker::s_loadProgress;
Worker::Worker( const char* addr, int port )
: m_addr( addr )
, m_port( port )
, m_hasData( false )
, m_stream( LZ4_createStreamDecode() )
, m_buffer( new char[TargetFrameSize*3 + 1] )
, m_bufferOffset( 0 )
, m_pendingStrings( 0 )
, m_pendingThreads( 0 )
, m_pendingExternalNames( 0 )
, m_pendingSourceLocation( 0 )
2018-06-20 21:42:00 +00:00
, m_pendingCallstackFrames( 0 )
, m_pendingCallstackSubframes( 0 )
, m_callstackFrameStaging( nullptr )
2018-07-29 13:33:48 +00:00
, m_traceVersion( CurrentVersion )
2019-01-06 18:09:50 +00:00
, m_loadTime( 0 )
{
m_data.sourceLocationExpand.push_back( 0 );
m_data.localThreadCompress.InitZero();
2018-06-19 19:52:54 +00:00
m_data.callstackPayload.push_back( nullptr );
memset( m_gpuCtxMap, 0, sizeof( m_gpuCtxMap ) );
#ifndef TRACY_NO_STATISTICS
m_data.sourceLocationZonesReady = true;
m_data.ctxUsageReady = true;
#endif
2019-08-14 00:26:54 +00:00
m_thread = std::thread( [this] { SetThreadName( "Tracy Worker" ); Exec(); } );
2019-10-28 21:45:10 +00:00
m_threadNet = std::thread( [this] { SetThreadName( "Tracy Network" ); Network(); } );
}
Worker::Worker( const std::string& program, const std::vector<ImportEventTimeline>& timeline, const std::vector<ImportEventMessages>& messages )
: m_hasData( true )
, m_stream( nullptr )
, m_buffer( nullptr )
, m_traceVersion( CurrentVersion )
, m_captureProgram( program )
2019-12-16 19:42:24 +00:00
, m_captureTime( 0 )
, m_resolution( 0 )
, m_delay( 0 )
, m_pid( 0 )
{
m_data.sourceLocationExpand.push_back( 0 );
m_data.localThreadCompress.InitZero();
m_data.callstackPayload.push_back( nullptr );
m_data.lastTime = 0;
if( !timeline.empty() )
{
m_data.lastTime = timeline.back().timestamp;
}
if( !messages.empty() )
{
if( m_data.lastTime < messages.back().timestamp ) m_data.lastTime = messages.back().timestamp;
}
for( auto& v : timeline )
{
if( !v.isEnd )
{
SourceLocation srcloc {
StringRef(),
StringRef( StringRef::Idx, StoreString( v.name.c_str(), v.name.size() ).idx ),
StringRef(),
0,
0
};
int key;
auto it = m_data.sourceLocationPayloadMap.find( &srcloc );
if( it == m_data.sourceLocationPayloadMap.end() )
{
auto slptr = m_slab.Alloc<SourceLocation>();
memcpy( slptr, &srcloc, sizeof( srcloc ) );
uint32_t idx = m_data.sourceLocationPayload.size();
m_data.sourceLocationPayloadMap.emplace( slptr, idx );
m_data.sourceLocationPayload.push_back( slptr );
key = -int16_t( idx + 1 );
#ifndef TRACY_NO_STATISTICS
auto res = m_data.sourceLocationZones.emplace( key, SourceLocationZones() );
m_data.srclocZonesLast.first = key;
m_data.srclocZonesLast.second = &res.first->second;
#else
auto res = m_data.sourceLocationZonesCnt.emplace( key, 0 );
m_data.srclocCntLast.first = key;
m_data.srclocCntLast.second = &res.first->second;
#endif
}
else
{
key = -int16_t( it->second + 1 );
}
auto zone = AllocZoneEvent();
zone->SetStart( v.timestamp );
zone->SetEnd( -1 );
zone->SetSrcLoc( key );
zone->SetChild( -1 );
m_threadCtxData = NoticeThread( v.tid );
NewZone( zone, v.tid );
}
else
{
auto td = NoticeThread( v.tid );
td->zoneIdStack.back_and_pop();
auto& stack = td->stack;
auto zone = stack.back_and_pop();
zone->SetEnd( v.timestamp );
}
}
for( auto& v : messages )
{
auto msg = m_slab.Alloc<MessageData>();
msg->time = v.timestamp;
msg->ref = StringRef( StringRef::Type::Idx, StoreString( v.message.c_str(), v.message.size() ).idx );
msg->thread = CompressThread( v.tid );
msg->color = 0xFFFFFFFF;
msg->callstack.SetVal( 0 );
InsertMessageData( msg );
}
for( auto& t : m_threadMap )
{
char buf[64];
sprintf( buf, "%i", t.first );
AddThreadString( t.first, buf, strlen( buf ) );
}
m_data.framesBase = m_data.frames.Retrieve( 0, [this] ( uint64_t name ) {
auto fd = m_slab.AllocInit<FrameData>();
fd->name = name;
fd->continuous = 1;
return fd;
}, [this] ( uint64_t name ) {
assert( name == 0 );
char tmp[6] = "Frame";
HandleFrameName( name, tmp, 5 );
} );
m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );
m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );
}
Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
: m_hasData( true )
, m_stream( nullptr )
, m_buffer( nullptr )
{
2019-01-06 18:09:50 +00:00
auto loadStart = std::chrono::high_resolution_clock::now();
2018-06-19 19:52:54 +00:00
m_data.callstackPayload.push_back( nullptr );
2018-04-21 11:45:48 +00:00
int fileVer = 0;
uint8_t hdr[8];
f.Read( hdr, sizeof( hdr ) );
if( memcmp( FileHeader, hdr, FileHeaderMagic ) == 0 )
{
fileVer = FileVersion( hdr[FileHeaderMagic], hdr[FileHeaderMagic+1], hdr[FileHeaderMagic+2] );
if( fileVer > CurrentVersion )
{
throw UnsupportedVersion( fileVer );
}
2019-08-12 10:27:35 +00:00
if( fileVer < MinSupportedVersion )
{
throw LegacyVersion( fileVer );
}
2018-04-30 23:47:56 +00:00
f.Read( m_delay );
2018-04-21 11:45:48 +00:00
}
else
{
2019-08-12 10:27:35 +00:00
throw LegacyVersion( FileVersion( 0, 2, 0 ) );
2018-04-21 11:45:48 +00:00
}
2018-07-29 13:33:48 +00:00
m_traceVersion = fileVer;
2018-04-21 11:45:48 +00:00
2019-11-21 20:48:35 +00:00
if( fileVer == FileVersion( 0, 5, 0 ) )
2019-06-06 21:40:37 +00:00
{
s_loadProgress.total.store( 9, std::memory_order_relaxed );
}
2019-08-16 14:51:02 +00:00
else if( fileVer <= FileVersion( 0, 5, 2 ) )
2019-08-12 22:56:57 +00:00
{
s_loadProgress.total.store( 10, std::memory_order_relaxed );
}
2019-08-16 14:51:02 +00:00
else
{
s_loadProgress.total.store( 11, std::memory_order_relaxed );
}
2018-07-28 15:59:17 +00:00
2018-07-28 16:56:52 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::Initialization, std::memory_order_relaxed );
2019-11-08 23:43:06 +00:00
f.Read4( m_resolution, m_timerMul, m_data.lastTime, m_data.frameOffset );
2018-07-10 20:56:41 +00:00
2019-08-17 20:19:04 +00:00
if( fileVer >= FileVersion( 0, 5, 5 ) )
{
f.Read( m_pid );
}
else
{
m_pid = 0;
}
uint64_t sz;
{
2018-04-30 23:47:56 +00:00
f.Read( sz );
assert( sz < 1024 );
char tmp[1024];
f.Read( tmp, sz );
m_captureName = std::string( tmp, tmp+sz );
}
{
f.Read( sz );
assert( sz < 1024 );
char tmp[1024];
f.Read( tmp, sz );
m_captureProgram = std::string( tmp, tmp+sz );
f.Read( m_captureTime );
}
2018-08-19 16:28:48 +00:00
{
f.Read( sz );
assert( sz < 1024 );
char tmp[1024];
f.Read( tmp, sz );
m_hostInfo = std::string( tmp, tmp+sz );
}
if( fileVer >= FileVersion( 0, 6, 2 ) )
{
f.Read( sz );
m_data.cpuTopology.reserve( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint32_t packageId;
uint64_t psz;
f.Read2( packageId, psz );
auto& package = *m_data.cpuTopology.emplace( packageId, flat_hash_map<uint32_t, std::vector<uint32_t>> {} ).first;
package.second.reserve( psz );
for( uint64_t j=0; j<psz; j++ )
{
uint32_t coreId;
uint64_t csz;
f.Read2( coreId, csz );
auto& core = *package.second.emplace( coreId, std::vector<uint32_t> {} ).first;
core.second.reserve( csz );
for( uint64_t k=0; k<csz; k++ )
{
uint32_t thread;
f.Read( thread );
core.second.emplace_back( thread );
2019-11-29 21:46:57 +00:00
m_data.cpuTopologyMap.emplace( thread, CpuThreadTopology { packageId, coreId } );
}
}
}
}
2019-08-12 10:27:35 +00:00
f.Read( &m_data.crashEvent, sizeof( m_data.crashEvent ) );
2018-08-20 00:27:24 +00:00
2019-08-12 10:27:35 +00:00
f.Read( sz );
m_data.frames.Data().reserve_exact( sz, m_slab );
for( uint64_t i=0; i<sz; i++ )
2018-08-04 17:47:09 +00:00
{
2019-08-12 10:27:35 +00:00
auto ptr = m_slab.AllocInit<FrameData>();
uint64_t fsz;
2019-11-08 23:43:06 +00:00
f.Read3( ptr->name, ptr->continuous, fsz );
2019-08-12 10:27:35 +00:00
ptr->frames.reserve_exact( fsz, m_slab );
2019-11-21 20:48:35 +00:00
int64_t refTime = 0;
if( ptr->continuous )
2019-08-12 10:27:35 +00:00
{
2019-11-21 20:48:35 +00:00
for( uint64_t j=0; j<fsz; j++ )
2018-08-05 00:09:59 +00:00
{
2019-11-21 20:48:35 +00:00
ptr->frames[j].start = ReadTimeOffset( f, refTime );
ptr->frames[j].end = -1;
f.Read( &ptr->frames[j].frameImage, sizeof( int32_t ) );
2018-08-05 00:09:59 +00:00
}
2019-08-12 10:27:35 +00:00
}
else
{
2019-11-21 20:48:35 +00:00
for( uint64_t j=0; j<fsz; j++ )
2018-08-05 00:09:59 +00:00
{
2019-11-21 20:48:35 +00:00
ptr->frames[j].start = ReadTimeOffset( f, refTime );
ptr->frames[j].end = ReadTimeOffset( f, refTime );
f.Read( &ptr->frames[j].frameImage, sizeof( int32_t ) );
2018-08-05 00:09:59 +00:00
}
}
2019-09-16 19:31:43 +00:00
for( uint64_t j=0; j<fsz; j++ )
{
const auto timeSpan = GetFrameTime( *ptr, j );
if( timeSpan > 0 )
{
ptr->min = std::min( ptr->min, timeSpan );
ptr->max = std::max( ptr->max, timeSpan );
ptr->total += timeSpan;
ptr->sumSq += double( timeSpan ) * timeSpan;
}
}
2019-08-12 10:27:35 +00:00
m_data.frames.Data()[i] = ptr;
2018-08-04 17:47:09 +00:00
}
2019-08-12 10:27:35 +00:00
m_data.framesBase = m_data.frames.Data()[0];
assert( m_data.framesBase->name == 0 );
2019-08-15 16:48:52 +00:00
if( fileVer < FileVersion( 0, 5, 2 ) )
{
m_data.baseTime = m_data.framesBase->frames[0].start;
m_data.lastTime -= m_data.baseTime;
if( m_data.crashEvent.time != 0 ) m_data.crashEvent.time -= m_data.baseTime;
for( auto& fd : m_data.frames.Data() )
{
if( fd->continuous )
{
for( auto& fe : fd->frames )
{
fe.start -= m_data.baseTime;
}
}
else
{
for( auto& fe : fd->frames )
{
fe.start -= m_data.baseTime;
fe.end -= m_data.baseTime;
}
}
}
}
flat_hash_map<uint64_t, const char*, nohash<uint64_t>> pointerMap;
2018-04-30 23:47:56 +00:00
f.Read( sz );
m_data.stringData.reserve_exact( sz, m_slab );
for( uint64_t i=0; i<sz; i++ )
{
2018-04-30 23:47:56 +00:00
uint64_t ptr, ssz;
f.Read2( ptr, ssz );
auto dst = m_slab.Alloc<char>( ssz+1 );
f.Read( dst, ssz );
dst[ssz] = '\0';
m_data.stringData[i] = ( dst );
pointerMap.emplace( ptr, dst );
}
2018-04-30 23:47:56 +00:00
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t id, ptr;
2018-04-30 23:47:56 +00:00
f.Read2( id, ptr );
auto it = pointerMap.find( ptr );
if( it != pointerMap.end() )
{
m_data.strings.emplace( id, it->second );
}
}
2018-04-30 23:47:56 +00:00
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t id, ptr;
2018-04-30 23:47:56 +00:00
f.Read2( id, ptr );
auto it = pointerMap.find( ptr );
if( it != pointerMap.end() )
{
m_data.threadNames.emplace( id, it->second );
}
}
2019-08-16 17:24:38 +00:00
if( fileVer >= FileVersion( 0, 5, 3 ) )
{
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
2019-08-16 17:49:16 +00:00
uint64_t id, ptr, ptr2;
2019-11-08 23:43:06 +00:00
f.Read3( id, ptr, ptr2 );
2019-08-16 17:24:38 +00:00
auto it = pointerMap.find( ptr );
2019-08-16 17:49:16 +00:00
auto it2 = pointerMap.find( ptr2 );
if( it != pointerMap.end() && it2 != pointerMap.end() )
2019-08-16 17:24:38 +00:00
{
2019-08-16 17:49:16 +00:00
m_data.externalNames.emplace( id, std::make_pair( it->second, it2->second ) );
2019-08-16 17:24:38 +00:00
}
}
}
m_data.localThreadCompress.Load( f, fileVer );
if( fileVer >= FileVersion( 0, 5, 6 ) )
{
m_data.externalThreadCompress.Load( f, fileVer );
}
2018-04-30 23:47:56 +00:00
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t ptr;
2018-04-30 23:47:56 +00:00
f.Read( ptr );
SourceLocation srcloc;
f.Read( &srcloc, sizeof( SourceLocationBase ) );
srcloc.namehash = 0;
m_data.sourceLocation.emplace( ptr, srcloc );
}
2018-04-30 23:47:56 +00:00
f.Read( sz );
m_data.sourceLocationExpand.reserve_exact( sz, m_slab );
2018-03-15 20:42:00 +00:00
f.Read( m_data.sourceLocationExpand.data(), sizeof( uint64_t ) * sz );
2018-03-18 01:05:33 +00:00
const auto sle = sz;
2018-04-30 23:47:56 +00:00
f.Read( sz );
m_data.sourceLocationPayload.reserve_exact( sz, m_slab );
for( uint64_t i=0; i<sz; i++ )
{
auto srcloc = m_slab.Alloc<SourceLocation>();
f.Read( srcloc, sizeof( SourceLocationBase ) );
srcloc->namehash = 0;
m_data.sourceLocationPayload[i] = srcloc;
m_data.sourceLocationPayloadMap.emplace( srcloc, int16_t( i ) );
}
#ifndef TRACY_NO_STATISTICS
m_data.sourceLocationZonesReady = false;
2018-03-18 01:05:33 +00:00
m_data.sourceLocationZones.reserve( sle + sz );
2019-08-12 10:27:35 +00:00
f.Read( sz );
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
for( uint64_t i=0; i<sz; i++ )
{
int16_t id;
uint64_t cnt;
2019-11-08 23:43:06 +00:00
f.Read2( id, cnt );
auto status = m_data.sourceLocationZones.emplace( id, SourceLocationZones() );
assert( status.second );
status.first->second.zones.reserve( cnt );
}
}
else
2018-03-18 01:05:33 +00:00
{
for( uint64_t i=0; i<sz; i++ )
{
int32_t id;
uint64_t cnt;
2019-11-08 23:43:06 +00:00
f.Read2( id, cnt );
auto status = m_data.sourceLocationZones.emplace( int16_t( id ), SourceLocationZones() );
assert( status.second );
status.first->second.zones.reserve( cnt );
}
}
#else
2019-08-12 10:27:35 +00:00
f.Read( sz );
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
for( uint64_t i=0; i<sz; i++ )
{
int16_t id;
f.Read( id );
f.Skip( sizeof( uint64_t ) );
m_data.sourceLocationZonesCnt.emplace( id, 0 );
}
}
else
{
for( uint64_t i=0; i<sz; i++ )
{
int32_t id;
f.Read( id );
f.Skip( sizeof( uint64_t ) );
m_data.sourceLocationZonesCnt.emplace( int16_t( id ), 0 );
}
2018-03-18 01:05:33 +00:00
}
#endif
2018-03-18 01:05:33 +00:00
s_loadProgress.progress.store( LoadProgress::Locks, std::memory_order_relaxed );
2018-04-30 23:47:56 +00:00
f.Read( sz );
2018-04-20 14:03:09 +00:00
if( eventMask & EventType::Locks )
{
2018-07-28 17:05:01 +00:00
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
2018-04-20 14:03:09 +00:00
for( uint64_t i=0; i<sz; i++ )
{
2018-07-28 17:05:01 +00:00
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
auto lockmapPtr = m_slab.AllocInit<LockMap>();
auto& lockmap = *lockmapPtr;
2018-04-20 14:03:09 +00:00
uint32_t id;
uint64_t tsz;
2018-04-30 23:47:56 +00:00
f.Read( id );
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
f.Read( lockmap.srcloc );
}
else
{
int32_t srcloc;
f.Read( srcloc );
lockmap.srcloc = int16_t( srcloc );
}
2019-11-08 23:43:06 +00:00
f.Read2( lockmap.type, lockmap.valid );
2019-05-12 14:17:17 +00:00
lockmap.isContended = false;
2019-08-15 16:48:52 +00:00
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
f.Read2( lockmap.timeAnnounce, lockmap.timeTerminate );
}
2019-11-21 20:48:35 +00:00
else
{
f.Read2( lockmap.timeAnnounce, lockmap.timeTerminate );
2019-08-15 16:48:52 +00:00
lockmap.timeAnnounce -= m_data.baseTime;
lockmap.timeTerminate -= m_data.baseTime;
if( lockmap.timeTerminate < lockmap.timeAnnounce ) lockmap.timeTerminate = 0;
}
2018-04-30 23:47:56 +00:00
f.Read( tsz );
2019-11-15 21:44:36 +00:00
lockmap.threadMap.reserve( tsz );
lockmap.threadList.reserve( tsz );
for( uint64_t i=0; i<tsz; i++ )
{
2018-04-20 14:03:09 +00:00
uint64_t t;
2018-04-30 23:47:56 +00:00
f.Read( t );
lockmap.threadMap.emplace( t, i );
2018-04-20 14:03:09 +00:00
lockmap.threadList.emplace_back( t );
}
2018-04-30 23:47:56 +00:00
f.Read( tsz );
lockmap.timeline.reserve_exact( tsz, m_slab );
2018-04-29 01:21:40 +00:00
auto ptr = lockmap.timeline.data();
if( fileVer >= FileVersion( 0, 5, 2 ) )
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
{
int64_t refTime = lockmap.timeAnnounce;
if( lockmap.type == LockType::Lockable )
{
for( uint64_t i=0; i<tsz; i++ )
{
auto lev = m_slab.Alloc<LockEvent>();
const auto lt = ReadTimeOffset( f, refTime );
lev->SetTime( lt );
int16_t srcloc;
f.Read( srcloc );
lev->SetSrcLoc( srcloc );
f.Read( &lev->thread, sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) );
*ptr++ = { lev };
UpdateLockRange( lockmap, *lev, lt );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
}
}
else
{
for( uint64_t i=0; i<tsz; i++ )
{
auto lev = m_slab.Alloc<LockEventShared>();
const auto lt = ReadTimeOffset( f, refTime );
lev->SetTime( lt );
int16_t srcloc;
f.Read( srcloc );
lev->SetSrcLoc( srcloc );
f.Read( &lev->thread, sizeof( LockEventShared::thread ) + sizeof( LockEventShared::type ) );
*ptr++ = { lev };
UpdateLockRange( lockmap, *lev, lt );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
}
}
}
2019-11-21 20:48:35 +00:00
else
{
int64_t refTime = lockmap.timeAnnounce;
if( lockmap.type == LockType::Lockable )
{
for( uint64_t i=0; i<tsz; i++ )
{
auto lev = m_slab.Alloc<LockEvent>();
const auto lt = ReadTimeOffset( f, refTime );
lev->SetTime( lt );
int32_t srcloc;
f.Read( srcloc );
lev->SetSrcLoc( int16_t( srcloc ) );
f.Read( &lev->thread, sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) );
*ptr++ = { lev };
UpdateLockRange( lockmap, *lev, lt );
}
}
else
{
for( uint64_t i=0; i<tsz; i++ )
{
auto lev = m_slab.Alloc<LockEventShared>();
const auto lt = ReadTimeOffset( f, refTime );
lev->SetTime( lt );
int32_t srcloc;
f.Read( srcloc );
lev->SetSrcLoc( int16_t( srcloc ) );
f.Read( &lev->thread, sizeof( LockEventShared::thread ) + sizeof( LockEventShared::type ) );
*ptr++ = { lev };
UpdateLockRange( lockmap, *lev, lt );
}
}
}
UpdateLockCount( lockmap, 0 );
m_data.lockMap.emplace( id, lockmapPtr );
2018-04-20 14:03:09 +00:00
}
}
else
{
for( uint64_t i=0; i<sz; i++ )
{
LockType type;
uint64_t tsz;
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
f.Skip( sizeof( uint32_t ) + sizeof( LockMap::srcloc ) );
}
else
{
f.Skip( sizeof( uint32_t ) + sizeof( int32_t ) );
}
2018-04-30 23:47:56 +00:00
f.Read( type );
2019-11-21 20:48:35 +00:00
f.Skip( sizeof( LockMap::valid ) + sizeof( LockMap::timeAnnounce ) + sizeof( LockMap::timeTerminate ) );
2018-04-30 23:47:56 +00:00
f.Read( tsz );
2018-04-20 14:03:09 +00:00
f.Skip( tsz * sizeof( uint64_t ) );
2018-04-30 23:47:56 +00:00
f.Read( tsz );
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
2019-08-29 23:16:42 +00:00
f.Skip( tsz * ( sizeof( int64_t ) + sizeof( int16_t ) + sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) ) );
}
else
{
2019-08-29 23:16:42 +00:00
f.Skip( tsz * ( sizeof( int64_t ) + sizeof( int32_t ) + sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) ) );
}
}
}
2018-07-28 17:05:01 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::Messages, std::memory_order_relaxed );
flat_hash_map<uint64_t, MessageData*, nohash<uint64_t>> msgMap;
2018-04-30 23:47:56 +00:00
f.Read( sz );
2018-04-20 14:03:09 +00:00
if( eventMask & EventType::Messages )
{
m_data.messages.reserve_exact( sz, m_slab );
2019-11-14 23:42:44 +00:00
if( fileVer >= FileVersion( 0, 5, 12 ) )
{
int64_t refTime = 0;
for( uint64_t i=0; i<sz; i++ )
{
uint64_t ptr;
f.Read( ptr );
auto msgdata = m_slab.Alloc<MessageData>();
msgdata->time = ReadTimeOffset( f, refTime );
f.Read3( msgdata->ref, msgdata->color, msgdata->callstack );
m_data.messages[i] = msgdata;
msgMap.emplace( ptr, msgdata );
}
}
else if( fileVer >= FileVersion( 0, 5, 2 ) )
2018-04-20 14:03:09 +00:00
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
for( uint64_t i=0; i<sz; i++ )
{
uint64_t ptr;
f.Read( ptr );
auto msgdata = m_slab.Alloc<MessageData>();
msgdata->time = ReadTimeOffset( f, refTime );
2019-11-08 23:43:06 +00:00
f.Read2( msgdata->ref, msgdata->color );
2019-11-14 23:42:44 +00:00
msgdata->callstack.SetVal( 0 );
m_data.messages[i] = msgdata;
msgMap.emplace( ptr, msgdata );
}
}
2019-11-21 20:48:35 +00:00
else
2019-08-15 16:48:52 +00:00
{
int64_t refTime = -m_data.baseTime;
for( uint64_t i=0; i<sz; i++ )
{
uint64_t ptr;
f.Read( ptr );
auto msgdata = m_slab.Alloc<MessageData>();
msgdata->time = ReadTimeOffset( f, refTime );
2019-11-08 23:43:06 +00:00
f.Read2( msgdata->ref, msgdata->color );
2019-11-14 23:42:44 +00:00
msgdata->callstack.SetVal( 0 );
2019-08-15 16:48:52 +00:00
m_data.messages[i] = msgdata;
msgMap.emplace( ptr, msgdata );
}
}
2018-04-20 14:03:09 +00:00
}
else
{
2019-11-14 23:42:44 +00:00
if( fileVer >= FileVersion( 0, 5, 12 ) )
{
2019-11-14 23:42:44 +00:00
f.Skip( sz * ( sizeof( uint64_t ) + sizeof( MessageData::time ) + sizeof( MessageData::ref ) + sizeof( MessageData::color ) + sizeof( MessageData::callstack ) ) );
}
2019-11-14 23:42:44 +00:00
else
{
2019-11-21 20:48:35 +00:00
f.Skip( sz * ( sizeof( uint64_t ) + sizeof( MessageData::time ) + sizeof( MessageData::ref ) + sizeof( MessageData::color ) ) );
2019-11-14 23:42:44 +00:00
}
}
s_loadProgress.progress.store( LoadProgress::Zones, std::memory_order_relaxed );
2019-11-21 20:48:35 +00:00
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
s_loadProgress.subProgress.store( 0, std::memory_order_relaxed );
if( fileVer >= FileVersion( 0, 5, 10 ) )
{
f.Read( sz );
m_data.zoneChildren.reserve_exact( sz, m_slab );
2019-11-02 15:17:20 +00:00
memset( m_data.zoneChildren.data(), 0, sizeof( Vector<short_ptr<ZoneEvent>> ) * sz );
}
int32_t childIdx = 0;
2018-04-30 23:47:56 +00:00
f.Read( sz );
m_data.threads.reserve_exact( sz, m_slab );
for( uint64_t i=0; i<sz; i++ )
{
auto td = m_slab.AllocInit<ThreadData>();
2019-11-08 23:43:06 +00:00
uint64_t tid, tsz;
f.Read3( tid, td->count, tsz );
2018-05-25 19:10:22 +00:00
td->id = tid;
2018-07-22 19:15:28 +00:00
if( tsz != 0 )
{
2019-11-21 20:48:35 +00:00
if( fileVer <= FileVersion( 0, 5, 9 ) )
2019-08-12 17:18:17 +00:00
{
int64_t refTime = 0;
ReadTimelinePre0510( f, td->timeline, tsz, refTime, fileVer );
2019-08-12 17:18:17 +00:00
}
2018-07-22 19:15:28 +00:00
else
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
ReadTimeline( f, td->timeline, tsz, refTime, childIdx );
2018-07-22 19:15:28 +00:00
}
}
uint64_t msz;
2018-04-30 23:47:56 +00:00
f.Read( msz );
2018-04-20 14:03:09 +00:00
if( eventMask & EventType::Messages )
{
2019-08-28 19:03:01 +00:00
const auto ctid = CompressThread( tid );
td->messages.reserve_exact( msz, m_slab );
2018-04-20 14:03:09 +00:00
for( uint64_t j=0; j<msz; j++ )
{
uint64_t ptr;
2018-04-30 23:47:56 +00:00
f.Read( ptr );
2018-05-25 19:10:22 +00:00
auto md = msgMap[ptr];
td->messages[j] = md;
2019-08-28 19:03:01 +00:00
md->thread = ctid;
2018-04-20 14:03:09 +00:00
}
}
else
{
f.Skip( msz * sizeof( uint64_t ) );
}
m_data.threads[i] = td;
m_threadMap.emplace( tid, td );
}
s_loadProgress.progress.store( LoadProgress::GpuZones, std::memory_order_relaxed );
2019-11-21 20:48:35 +00:00
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
s_loadProgress.subProgress.store( 0, std::memory_order_relaxed );
if( fileVer >= FileVersion( 0, 5, 10 ) )
{
f.Read( sz );
m_data.gpuChildren.reserve_exact( sz, m_slab );
2019-11-02 15:57:18 +00:00
memset( m_data.gpuChildren.data(), 0, sizeof( Vector<short_ptr<GpuEvent>> ) * sz );
}
childIdx = 0;
2018-04-30 23:47:56 +00:00
f.Read( sz );
m_data.gpuData.reserve_exact( sz, m_slab );
for( uint64_t i=0; i<sz; i++ )
{
auto ctx = m_slab.AllocInit<GpuCtxData>();
2019-11-08 23:43:06 +00:00
f.Read4( ctx->thread, ctx->accuracyBits, ctx->count, ctx->period );
2019-11-09 22:57:08 +00:00
if( fileVer >= FileVersion( 0, 5, 10 ) )
{
2019-09-23 15:27:49 +00:00
uint64_t tdsz;
f.Read( tdsz );
for( uint64_t j=0; j<tdsz; j++ )
2018-07-22 19:15:28 +00:00
{
2019-09-23 15:27:49 +00:00
uint64_t tid, tsz;
f.Read2( tid, tsz );
if( tsz != 0 )
{
int64_t refTime = 0;
int64_t refGpuTime = 0;
auto td = ctx->threadData.emplace( tid, GpuCtxThreadData {} ).first;
ReadTimeline( f, td->second.timeline, tsz, refTime, refGpuTime, childIdx );
2019-09-23 15:27:49 +00:00
}
2018-07-22 19:15:28 +00:00
}
}
else if( fileVer >= FileVersion( 0, 5, 7 ) )
{
uint64_t tdsz;
f.Read( tdsz );
for( uint64_t j=0; j<tdsz; j++ )
{
uint64_t tid, tsz;
f.Read2( tid, tsz );
if( tsz != 0 )
{
int64_t refTime = 0;
int64_t refGpuTime = 0;
auto td = ctx->threadData.emplace( tid, GpuCtxThreadData {} ).first;
ReadTimelinePre0510( f, td->second.timeline, tsz, refTime, refGpuTime, fileVer );
}
}
2019-09-23 15:27:49 +00:00
}
else
{
uint64_t tsz;
f.Read( tsz );
if( tsz != 0 )
2018-07-22 19:15:28 +00:00
{
2019-09-23 15:27:49 +00:00
int64_t refTime = 0;
int64_t refGpuTime = 0;
auto td = ctx->threadData.emplace( 0, GpuCtxThreadData {} ).first;
ReadTimelinePre0510( f, td->second.timeline, tsz, refTime, refGpuTime, fileVer );
2018-07-22 19:15:28 +00:00
}
}
m_data.gpuData[i] = ctx;
}
s_loadProgress.progress.store( LoadProgress::Plots, std::memory_order_relaxed );
2018-04-30 23:47:56 +00:00
f.Read( sz );
2018-04-20 14:03:09 +00:00
if( eventMask & EventType::Plots )
{
2018-08-04 14:33:03 +00:00
m_data.plots.Data().reserve( sz );
2018-08-04 13:17:37 +00:00
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
2018-04-20 14:03:09 +00:00
for( uint64_t i=0; i<sz; i++ )
{
2018-08-04 13:17:37 +00:00
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
2018-04-20 14:03:09 +00:00
auto pd = m_slab.AllocInit<PlotData>();
if( fileVer >= FileVersion( 0, 5, 11 ) )
2019-02-21 21:53:26 +00:00
{
2019-11-08 23:43:06 +00:00
f.Read2( pd->type, pd->format );
2019-02-21 21:53:26 +00:00
}
else
{
2019-11-21 20:48:35 +00:00
f.Read( pd->type );
switch( pd->type )
{
case PlotType::User:
pd->format = PlotValueFormatting::Number;
break;
case PlotType::Memory:
pd->format = PlotValueFormatting::Memory;
break;
case PlotType::SysTime:
pd->format = PlotValueFormatting::Percentage;
break;
default:
assert( false );
break;
}
2019-02-21 21:53:26 +00:00
}
2018-04-20 14:03:09 +00:00
uint64_t psz;
2019-11-08 23:43:06 +00:00
f.Read4( pd->name, pd->min, pd->max, psz );
pd->data.reserve_exact( psz, m_slab );
2019-08-15 16:48:52 +00:00
if( fileVer >= FileVersion( 0, 5, 2 ) )
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
{
int64_t refTime = 0;
for( uint64_t j=0; j<psz; j++ )
{
pd->data[j].time.SetVal( ReadTimeOffset( f, refTime ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
f.Read( pd->data[j].val );
}
}
2019-11-21 20:48:35 +00:00
else
2019-08-15 16:48:52 +00:00
{
int64_t refTime = -m_data.baseTime;
for( uint64_t j=0; j<psz; j++ )
{
pd->data[j].time.SetVal( ReadTimeOffset( f, refTime ) );
2019-08-15 16:48:52 +00:00
f.Read( pd->data[j].val );
}
}
2018-08-04 14:33:03 +00:00
m_data.plots.Data().push_back_no_space_check( pd );
2018-04-20 14:03:09 +00:00
}
}
else
{
for( uint64_t i=0; i<sz; i++ )
{
if( fileVer >= FileVersion( 0, 5, 11 ) )
{
f.Skip( sizeof( PlotData::name ) + sizeof( PlotData::min ) + sizeof( PlotData::max ) + sizeof( PlotData::type ) + sizeof( PlotData::format ) );
}
else
{
2019-11-21 20:48:35 +00:00
f.Skip( sizeof( PlotData::name ) + sizeof( PlotData::min ) + sizeof( PlotData::max ) + sizeof( PlotData::type ) );
}
2018-04-20 14:03:09 +00:00
uint64_t psz;
2018-04-30 23:47:56 +00:00
f.Read( psz );
f.Skip( psz * ( sizeof( uint64_t ) + sizeof( double ) ) );
2018-04-20 14:03:09 +00:00
}
}
2018-04-02 00:05:16 +00:00
2019-02-14 00:13:11 +00:00
bool reconstructMemAllocPlot = false;
2018-07-28 17:05:01 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::Memory, std::memory_order_relaxed );
2018-04-30 23:47:56 +00:00
f.Read( sz );
2018-04-20 14:03:09 +00:00
if( eventMask & EventType::Memory )
2018-04-02 00:05:16 +00:00
{
m_data.memory.data.reserve_exact( sz, m_slab );
2019-08-12 10:27:35 +00:00
uint64_t activeSz, freesSz;
f.Read2( activeSz, freesSz );
m_data.memory.active.reserve( activeSz );
m_data.memory.frees.reserve_exact( freesSz, m_slab );
2018-04-20 14:03:09 +00:00
auto mem = m_data.memory.data.data();
2018-07-28 17:05:01 +00:00
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
size_t fidx = 0;
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
if( fileVer >= FileVersion( 0, 5, 9 ) )
{
auto& frees = m_data.memory.frees;
auto& active = m_data.memory.active;
for( uint64_t i=0; i<sz; i++ )
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
uint64_t ptr, size;
Int24 csAlloc;
2019-11-08 23:43:06 +00:00
f.Read4( ptr, size, csAlloc, mem->csFree );
mem->SetPtr( ptr );
mem->SetSize( size );
mem->SetCsAlloc( csAlloc.Val() );
int64_t timeAlloc, timeFree;
uint16_t threadAlloc, threadFree;
2019-11-08 23:43:06 +00:00
f.Read4( timeAlloc, timeFree, threadAlloc, threadFree );
refTime += timeAlloc;
mem->SetTimeAlloc( refTime );
if( timeFree >= 0 )
{
mem->SetTimeFree( timeFree + refTime );
frees[fidx++] = i;
}
else
{
mem->SetTimeFree( timeFree );
active.emplace( ptr, i );
}
mem->SetThreadAlloc( threadAlloc );
mem->SetThreadFree( threadFree );
mem++;
}
}
else if( fileVer >= FileVersion( 0, 5, 2 ) )
{
auto& frees = m_data.memory.frees;
auto& active = m_data.memory.active;
for( uint64_t i=0; i<sz; i++ )
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
uint64_t ptr, size;
Int24 csAlloc;
2019-11-08 23:43:06 +00:00
f.Read3( ptr, size, csAlloc );
mem->SetPtr( ptr );
mem->SetSize( size );
mem->SetCsAlloc( csAlloc.Val() );
f.Skip( 1 );
f.Read( &mem->csFree, sizeof( MemEvent::csFree ) );
f.Skip( 1 );
int64_t timeAlloc, timeFree;
uint16_t threadAlloc, threadFree;
2019-11-08 23:43:06 +00:00
f.Read4( timeAlloc, timeFree, threadAlloc, threadFree );
refTime += timeAlloc;
mem->SetTimeAlloc( refTime );
if( timeFree >= 0 )
{
mem->SetTimeFree( timeFree + refTime );
frees[fidx++] = i;
}
else
{
mem->SetTimeFree( timeFree );
active.emplace( ptr, i );
}
mem->SetThreadAlloc( threadAlloc );
mem->SetThreadFree( threadFree );
mem++;
}
}
2019-11-21 20:48:35 +00:00
else
2018-04-02 00:05:16 +00:00
{
auto& frees = m_data.memory.frees;
auto& active = m_data.memory.active;
for( uint64_t i=0; i<sz; i++ )
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
uint64_t ptr, size;
2019-11-08 23:43:06 +00:00
int64_t timeAlloc, timeFree;
f.Read4( ptr, size, timeAlloc, timeFree );
mem->SetPtr( ptr );
mem->SetSize( size );
Int24 csAlloc;
f.Read( &csAlloc, sizeof( csAlloc ) );
mem->SetCsAlloc( csAlloc.Val() );
f.Skip( 1 );
f.Read( mem->csFree );
f.Skip( 1 );
uint16_t threadAlloc, threadFree;
f.Read2( threadAlloc, threadFree );
refTime += timeAlloc;
2019-08-15 22:24:29 +00:00
mem->SetTimeAlloc( refTime - m_data.baseTime );
if( timeFree >= 0 )
{
2019-08-15 22:24:29 +00:00
mem->SetTimeFree( timeFree + refTime - m_data.baseTime );
frees[fidx++] = i;
}
else
{
mem->SetTimeFree( timeFree );
active.emplace( ptr, i );
}
mem->SetThreadAlloc( threadAlloc );
mem->SetThreadFree( threadFree );
mem++;
}
}
2019-11-08 23:43:06 +00:00
f.Read3( m_data.memory.high, m_data.memory.low, m_data.memory.usage );
if( sz != 0 )
{
2018-06-24 15:10:46 +00:00
reconstructMemAllocPlot = true;
}
2018-04-20 14:03:09 +00:00
}
else
{
2019-08-12 10:27:35 +00:00
f.Skip( 2 * sizeof( uint64_t ) );
if( fileVer >= FileVersion( 0, 5, 9 ) )
{
f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( Int24 ) + sizeof( Int24 ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) );
}
else if( fileVer >= FileVersion( 0, 5, 2 ) )
2018-06-19 19:54:12 +00:00
{
f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) );
}
2018-06-19 19:54:12 +00:00
else
{
2019-11-21 20:48:35 +00:00
f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( int64_t ) + sizeof( int64_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint16_t ) + sizeof( uint16_t ) ) );
2018-06-19 19:54:12 +00:00
}
2018-04-20 14:03:09 +00:00
f.Skip( sizeof( MemData::high ) + sizeof( MemData::low ) + sizeof( MemData::usage ) );
2018-04-02 00:05:16 +00:00
}
2018-06-19 20:04:26 +00:00
2018-07-28 17:05:01 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::CallStacks, std::memory_order_relaxed );
2018-06-19 20:04:26 +00:00
f.Read( sz );
m_data.callstackPayload.reserve( sz );
2019-11-21 20:48:35 +00:00
for( uint64_t i=0; i<sz; i++ )
2018-06-19 20:04:26 +00:00
{
2019-11-21 20:48:35 +00:00
uint8_t csz;
f.Read( csz );
2018-06-19 20:04:26 +00:00
2019-11-21 20:48:35 +00:00
const auto memsize = sizeof( VarArray<CallstackFrameId> ) + csz * sizeof( CallstackFrameId );
auto mem = (char*)m_slab.AllocRaw( memsize );
2018-06-19 20:04:26 +00:00
2019-11-21 20:48:35 +00:00
auto data = (CallstackFrameId*)mem;
f.Read( data, csz * sizeof( CallstackFrameId ) );
2018-06-19 20:04:26 +00:00
2019-11-21 20:48:35 +00:00
auto arr = (VarArray<CallstackFrameId>*)( mem + csz * sizeof( CallstackFrameId ) );
new(arr) VarArray<CallstackFrameId>( csz, data );
2018-06-19 20:04:26 +00:00
2019-11-21 20:48:35 +00:00
m_data.callstackPayload.push_back_no_space_check( arr );
2018-06-19 20:04:26 +00:00
}
2018-06-19 23:59:25 +00:00
if( fileVer >= FileVersion( 0, 5, 8 ) )
{
f.Read( sz );
m_data.callstackFrameMap.reserve( sz );
for( uint64_t i=0; i<sz; i++ )
{
CallstackFrameId id;
auto frameData = m_slab.Alloc<CallstackFrameData>();
2019-11-08 23:43:06 +00:00
f.Read2( id, frameData->size );
frameData->data = m_slab.Alloc<CallstackFrame>( frameData->size );
f.Read( frameData->data, sizeof( CallstackFrame ) * frameData->size );
m_data.callstackFrameMap.emplace( id, frameData );
}
}
2019-11-21 20:48:35 +00:00
else
{
f.Read( sz );
m_data.callstackFrameMap.reserve( sz );
for( uint64_t i=0; i<sz; i++ )
{
__StringIdxOld str;
CallstackFrameId id;
auto frameData = m_slab.Alloc<CallstackFrameData>();
2019-11-08 23:43:06 +00:00
f.Read2( id, frameData->size );
frameData->data = m_slab.AllocInit<CallstackFrame>( frameData->size );
for( uint8_t j=0; j<frameData->size; j++ )
{
f.Read( str );
if( str.active ) frameData->data[j].name.SetIdx( str.idx );
f.Read( str );
if( str.active ) frameData->data[j].file.SetIdx( str.idx );
f.Read( frameData->data[j].line );
}
m_data.callstackFrameMap.emplace( id, frameData );
}
}
2018-06-19 23:59:25 +00:00
2019-11-21 20:48:35 +00:00
f.Read( sz );
if( sz > 0 )
{
2019-11-21 20:48:35 +00:00
m_data.appInfo.reserve_exact( sz, m_slab );
f.Read( m_data.appInfo.data(), sizeof( m_data.appInfo[0] ) * sz );
2018-06-19 23:59:25 +00:00
}
2018-06-24 15:10:46 +00:00
2019-11-21 20:48:35 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::FrameImages, std::memory_order_relaxed );
if( eventMask & EventType::FrameImages )
2019-07-12 16:45:35 +00:00
{
f.Read( sz );
2019-11-21 20:48:35 +00:00
m_data.frameImage.reserve_exact( sz, m_slab );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
if( sz != 0 )
2019-07-12 16:45:35 +00:00
{
2019-11-21 20:48:35 +00:00
struct JobData
{
enum State : int { InProgress, Available, DataReady };
FrameImage* fi;
char* buf = nullptr;
size_t bufsz = 0;
char* outbuf = nullptr;
size_t outsz = 0;
std::atomic<State> state = Available;
};
2019-07-12 16:45:35 +00:00
2019-11-21 20:48:35 +00:00
// Leave one thread for file reader, second thread for dispatch (this thread)
// Minimum 2 threads to have at least two buffers (one in use, second one filling up)
const auto jobs = std::max<int>( std::thread::hardware_concurrency() - 2, 2 );
auto td = std::make_unique<TaskDispatch>( jobs );
auto data = std::make_unique<JobData[]>( jobs );
2019-06-06 21:40:37 +00:00
2019-11-21 20:48:35 +00:00
for( uint64_t i=0; i<sz; i++ )
2019-06-06 21:08:19 +00:00
{
2019-11-21 20:48:35 +00:00
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
auto fi = m_slab.Alloc<FrameImage>();
f.Read3( fi->w, fi->h, fi->flip );
const auto sz = size_t( fi->w * fi->h / 2 );
2019-09-20 21:03:12 +00:00
2019-11-21 20:48:35 +00:00
int idx = -1;
for(;;)
{
for( int j=0; j<jobs; j++ )
2019-09-20 21:03:12 +00:00
{
2019-11-21 20:48:35 +00:00
const auto state = data[j].state.load( std::memory_order_acquire );
if( state != JobData::InProgress )
2019-09-20 21:03:12 +00:00
{
2019-11-21 20:48:35 +00:00
if( state == JobData::DataReady )
2019-09-20 21:03:12 +00:00
{
2019-11-21 20:48:35 +00:00
char* tmp = (char*)m_slab.AllocBig( data[j].fi->csz );
memcpy( tmp, data[j].outbuf, data[j].fi->csz );
data[j].fi->ptr = tmp;
2019-09-20 21:03:12 +00:00
}
2019-11-21 20:48:35 +00:00
idx = j;
break;
2019-09-20 21:03:12 +00:00
}
}
2019-11-21 20:48:35 +00:00
if( idx >= 0 ) break;
std::this_thread::yield();
}
2019-09-20 21:03:12 +00:00
2019-11-21 20:48:35 +00:00
if( data[idx].bufsz < sz )
{
data[idx].bufsz = sz;
delete[] data[idx].buf;
data[idx].buf = new char[sz];
}
f.Read( data[idx].buf, sz );
data[idx].fi = fi;
2019-09-20 21:03:12 +00:00
2019-11-21 20:48:35 +00:00
data[idx].state.store( JobData::InProgress, std::memory_order_release );
td->Queue( [this, &data, idx, fi] {
PackFrameImage( data[idx].outbuf, data[idx].outsz, data[idx].buf, fi->w * fi->h / 2, fi->csz );
data[idx].state.store( JobData::DataReady, std::memory_order_release );
} );
2019-09-20 21:03:12 +00:00
2019-11-21 20:48:35 +00:00
m_data.frameImage[i] = fi;
}
td->Sync();
td.reset();
for( size_t i=0; i<jobs; i++ )
{
if( data[i].state.load( std::memory_order_acquire ) == JobData::DataReady )
2019-06-08 10:17:18 +00:00
{
2019-11-21 20:48:35 +00:00
char* tmp = (char*)m_slab.AllocBig( data[i].fi->csz );
memcpy( tmp, data[i].outbuf, data[i].fi->csz );
data[i].fi->ptr = tmp;
2019-06-08 10:17:18 +00:00
}
2019-11-21 20:48:35 +00:00
delete[] data[i].buf;
delete[] data[i].outbuf;
}
2019-06-11 22:55:02 +00:00
2019-11-21 20:48:35 +00:00
const auto& frames = GetFramesBase()->frames;
const auto fsz = uint32_t( frames.size() );
for( uint32_t i=0; i<fsz; i++ )
{
const auto& f = frames[i];
if( f.frameImage != -1 )
2019-06-11 22:55:02 +00:00
{
2019-11-21 20:48:35 +00:00
m_data.frameImage[f.frameImage]->frameRef = i;
2019-06-11 22:55:02 +00:00
}
}
2019-06-06 21:08:19 +00:00
}
2019-11-21 20:48:35 +00:00
}
else
{
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
for( uint64_t i=0; i<sz; i++ )
2019-06-06 21:08:19 +00:00
{
2019-11-21 20:48:35 +00:00
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
uint16_t w, h;
f.Read2( w, h );
const auto fisz = w * h / 2;
f.Skip( fisz + sizeof( FrameImage::flip ) );
2019-06-06 21:08:19 +00:00
}
}
if( fileVer >= FileVersion( 0, 5, 6 ) )
2019-08-12 22:56:57 +00:00
{
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::ContextSwitches, std::memory_order_relaxed );
if( eventMask & EventType::ContextSwitches )
{
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
m_data.ctxSwitch.reserve( sz );
for( uint64_t i=0; i<sz; i++ )
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
uint64_t thread, csz;
f.Read2( thread, csz );
auto data = m_slab.AllocInit<ContextSwitch>();
data->v.reserve_exact( csz, m_slab );
int64_t runningTime = 0;
2019-08-12 22:56:57 +00:00
int64_t refTime = 0;
auto ptr = data->v.data();
for( uint64_t j=0; j<csz; j++ )
{
ptr->SetWakeup( ReadTimeOffset( f, refTime ) );
ptr->SetStart( ReadTimeOffset( f, refTime ) );
int64_t diff;
f.Read( diff );
if( diff > 0 ) runningTime += diff;
refTime += diff;
ptr->SetEnd( refTime );
uint8_t cpu;
int8_t reason;
int8_t state;
2019-11-08 23:43:06 +00:00
f.Read3( cpu, reason, state );
ptr->SetCpu( cpu );
ptr->SetReason( reason );
ptr->SetState( state );
2019-08-12 22:56:57 +00:00
ptr++;
}
data->runningTime = runningTime;
2019-08-12 22:56:57 +00:00
m_data.ctxSwitch.emplace( thread, data );
}
}
else
{
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
for( uint64_t i=0; i<sz; i++ )
{
s_loadProgress.subProgress.store( i, std::memory_order_relaxed );
f.Skip( sizeof( uint64_t ) );
uint64_t csz;
f.Read( csz );
2019-08-29 23:16:42 +00:00
f.Skip( csz * ( sizeof( int64_t ) * 3 + sizeof( int8_t ) * 3 ) );
2019-08-12 22:56:57 +00:00
}
}
2019-08-16 14:51:02 +00:00
s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );
s_loadProgress.progress.store( LoadProgress::ContextSwitchesPerCpu, std::memory_order_relaxed );
f.Read( sz );
s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );
if( eventMask & EventType::ContextSwitches )
{
uint64_t cnt = 0;
for( int i=0; i<256; i++ )
{
int64_t refTime = 0;
f.Read( sz );
if( sz != 0 )
2019-08-16 14:51:02 +00:00
{
m_data.cpuDataCount = i+1;
m_data.cpuData[i].cs.reserve_exact( sz, m_slab );
auto ptr = m_data.cpuData[i].cs.data();
for( uint64_t j=0; j<sz; j++ )
{
ptr->SetStart( ReadTimeOffset( f, refTime ) );
ptr->SetEnd( ReadTimeOffset( f, refTime ) );
uint16_t thread;
f.Read( thread );
ptr->SetThread( thread );
ptr++;
}
cnt += sz;
2019-08-16 14:51:02 +00:00
}
s_loadProgress.subProgress.store( cnt, std::memory_order_relaxed );
}
}
else
{
for( int i=0; i<256; i++ )
{
f.Read( sz );
2019-08-29 23:16:42 +00:00
f.Skip( sz * ( sizeof( int64_t ) * 2 + sizeof( uint16_t ) ) );
2019-08-16 14:51:02 +00:00
}
}
2019-08-17 20:36:21 +00:00
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t tid, pid;
f.Read2( tid, pid );
m_data.tidToPid.emplace( tid, pid );
}
2019-08-17 23:53:38 +00:00
f.Read( sz );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t tid;
CpuThreadData data;
2019-11-08 23:43:06 +00:00
f.Read2( tid, data );
2019-08-17 23:53:38 +00:00
m_data.cpuThreadData.emplace( tid, data );
}
2019-08-17 20:36:21 +00:00
}
s_loadProgress.total.store( 0, std::memory_order_relaxed );
m_loadTime = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now() - loadStart ).count();
if( !bgTasks )
{
m_backgroundDone.store( true, std::memory_order_relaxed );
}
else
{
m_backgroundDone.store( false, std::memory_order_relaxed );
#ifndef TRACY_NO_STATISTICS
m_threadBackground = std::thread( [this, reconstructMemAllocPlot] {
2019-11-02 15:17:20 +00:00
std::function<void(Vector<short_ptr<ZoneEvent>>&, uint16_t)> ProcessTimeline;
ProcessTimeline = [this, &ProcessTimeline] ( Vector<short_ptr<ZoneEvent>>& _vec, uint16_t thread )
{
if( m_shutdown.load( std::memory_order_relaxed ) ) return;
assert( _vec.is_magic() );
auto& vec = *(Vector<ZoneEvent>*)( &_vec );
for( auto& zone : vec )
{
2019-11-08 22:53:43 +00:00
ReconstructZoneStatistics( zone, thread );
if( zone.Child() >= 0 )
{
ProcessTimeline( GetZoneChildrenMutable( zone.Child() ), thread );
}
}
};
for( auto& t : m_data.threads )
{
if( m_shutdown.load( std::memory_order_relaxed ) ) return;
if( !t->timeline.empty() )
{
// Don't touch thread compression cache in a thread.
ProcessTimeline( t->timeline, m_data.localThreadCompress.DecompressMustRaw( t->id ) );
}
}
for( auto& v : m_data.sourceLocationZones )
{
if( m_shutdown.load( std::memory_order_relaxed ) ) return;
auto& zones = v.second.zones;
#ifdef MY_LIBCPP_SUCKS
pdqsort_branchless( zones.begin(), zones.end(), []( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs.Zone()->Start(); } );
#else
std::sort( std::execution::par_unseq, zones.begin(), zones.end(), []( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs.Zone()->Start(); } );
#endif
}
{
std::lock_guard<std::shared_mutex> lock( m_data.lock );
m_data.sourceLocationZonesReady = true;
}
if( m_shutdown.load( std::memory_order_relaxed ) ) return;
if( !m_data.ctxSwitch.empty() ) ReconstructContextSwitchUsage();
if( m_shutdown.load( std::memory_order_relaxed ) ) return;
if( reconstructMemAllocPlot ) ReconstructMemAllocPlot();
m_backgroundDone.store( true, std::memory_order_relaxed );
} );
#else
if( reconstructMemAllocPlot )
{
m_threadBackground = std::thread( [this] { ReconstructMemAllocPlot(); m_backgroundDone.store( true, std::memory_order_relaxed ); } );
}
m_backgroundDone.store( true, std::memory_order_relaxed );
#endif
}
}
Worker::~Worker()
{
Shutdown();
2019-10-28 21:45:10 +00:00
if( m_threadNet.joinable() ) m_threadNet.join();
if( m_thread.joinable() ) m_thread.join();
if( m_threadBackground.joinable() ) m_threadBackground.join();
2018-04-21 18:11:59 +00:00
delete[] m_buffer;
LZ4_freeStreamDecode( (LZ4_streamDecode_t*)m_stream );
2018-04-21 18:12:16 +00:00
2019-06-08 10:17:18 +00:00
delete[] m_frameImageBuffer;
delete[] m_frameImageCompressedBuffer;
2019-06-08 10:17:18 +00:00
2018-04-21 18:34:29 +00:00
for( auto& v : m_data.threads )
{
2018-07-22 19:01:45 +00:00
v->timeline.~Vector();
v->stack.~Vector();
2018-04-21 18:36:33 +00:00
v->messages.~Vector();
2019-06-09 15:56:41 +00:00
v->zoneIdStack.~Vector();
2019-10-26 21:11:48 +00:00
#ifndef TRACY_NO_STATISTICS
v->childTimeStack.~Vector();
#endif
2018-04-21 18:34:29 +00:00
}
2018-07-22 19:01:45 +00:00
for( auto& v : m_data.gpuData )
{
2019-09-23 15:27:49 +00:00
for( auto& vt : v->threadData )
{
vt.second.timeline.~Vector();
vt.second.stack.~Vector();
}
2018-07-22 19:01:45 +00:00
}
2018-08-04 14:33:03 +00:00
for( auto& v : m_data.plots.Data() )
2018-04-21 18:12:16 +00:00
{
v->~PlotData();
}
2018-08-04 17:47:09 +00:00
for( auto& v : m_data.frames.Data() )
{
v->~FrameData();
}
for( auto& v : m_data.lockMap )
{
v.second->~LockMap();
}
}
2018-08-08 17:21:53 +00:00
uint64_t Worker::GetLockCount() const
{
uint64_t cnt = 0;
for( auto& l : m_data.lockMap )
{
cnt += l.second->timeline.size();
2018-08-08 17:21:53 +00:00
}
return cnt;
}
uint64_t Worker::GetPlotCount() const
{
uint64_t cnt = 0;
for( auto& p : m_data.plots.Data() )
{
if( p->type != PlotType::Memory )
{
cnt += p->data.size();
}
}
return cnt;
}
uint64_t Worker::GetContextSwitchCount() const
{
uint64_t cnt = 0;
for( auto& v : m_data.ctxSwitch )
{
cnt += v.second->v.size();
}
return cnt;
}
uint64_t Worker::GetContextSwitchPerCpuCount() const
{
uint64_t cnt = 0;
2019-10-15 14:13:36 +00:00
for( int i=0; i<m_data.cpuDataCount; i++ )
{
cnt += m_data.cpuData[i].cs.size();
}
return cnt;
}
2019-08-17 23:51:02 +00:00
uint64_t Worker::GetPidFromTid( uint64_t tid ) const
{
auto it = m_data.tidToPid.find( tid );
if( it == m_data.tidToPid.end() ) return 0;
return it->second;
}
void Worker::GetCpuUsageAtTime( int64_t time, int& own, int& other ) const
{
own = other = 0;
2019-10-20 16:47:50 +00:00
if( time < 0 || time > m_data.lastTime ) return;
#ifndef TRACY_NO_STATISTICS
// Remove this check when real-time ctxUsage contruction is implemented.
if( !m_data.ctxUsage.empty() )
{
auto it = std::upper_bound( m_data.ctxUsage.begin(), m_data.ctxUsage.end(), time, [] ( const auto& l, const auto& r ) { return l < r.Time(); } );
if( it == m_data.ctxUsage.begin() || it == m_data.ctxUsage.end() ) return;
--it;
own = it->Own();
other = it->Other();
return;
}
#endif
for( int i=0; i<m_data.cpuDataCount; i++ )
{
auto& cs = m_data.cpuData[i].cs;
if( !cs.empty() )
{
auto it = std::lower_bound( cs.begin(), cs.end(), time, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
2019-10-16 18:26:39 +00:00
if( it != cs.end() && it->Start() <= time && it->End() >= 0 )
{
if( GetPidFromTid( DecompressThreadExternal( it->Thread() ) ) == m_pid )
{
own++;
}
else
{
other++;
}
}
}
}
}
2019-08-14 18:16:11 +00:00
const ContextSwitch* const Worker::GetContextSwitchDataImpl( uint64_t thread )
2019-08-12 22:20:56 +00:00
{
auto it = m_data.ctxSwitch.find( thread );
if( it != m_data.ctxSwitch.end() )
{
2019-08-14 18:16:11 +00:00
m_data.ctxSwitchLast.first = thread;
m_data.ctxSwitchLast.second = it->second;
2019-08-12 22:20:56 +00:00
return it->second;
}
else
{
return nullptr;
}
}
2018-09-01 10:38:12 +00:00
size_t Worker::GetFullFrameCount( const FrameData& fd ) const
{
const auto sz = fd.frames.size();
assert( sz != 0 );
if( fd.continuous )
{
if( IsConnected() )
{
return sz - 1;
}
else
{
return sz;
}
}
else
{
const auto& last = fd.frames.back();
if( last.end >= 0 )
{
return sz;
}
else
{
return sz - 1;
}
}
}
2018-08-04 17:47:09 +00:00
int64_t Worker::GetFrameTime( const FrameData& fd, size_t idx ) const
{
2018-08-05 00:09:59 +00:00
if( fd.continuous )
{
2018-08-05 00:09:59 +00:00
if( idx < fd.frames.size() - 1 )
{
return fd.frames[idx+1].start - fd.frames[idx].start;
}
else
{
assert( m_data.lastTime != 0 );
return m_data.lastTime - fd.frames.back().start;
}
}
else
{
2019-01-29 21:10:14 +00:00
const auto& frame = fd.frames[idx];
if( frame.end >= 0 )
2018-08-05 00:09:59 +00:00
{
2019-01-29 21:10:14 +00:00
return frame.end - frame.start;
2018-08-05 00:09:59 +00:00
}
else
{
return m_data.lastTime - fd.frames.back().start;
}
}
}
2018-08-04 17:47:09 +00:00
int64_t Worker::GetFrameBegin( const FrameData& fd, size_t idx ) const
{
2018-08-04 17:47:09 +00:00
assert( idx < fd.frames.size() );
2018-08-05 00:09:59 +00:00
return fd.frames[idx].start;
}
2018-08-04 17:47:09 +00:00
int64_t Worker::GetFrameEnd( const FrameData& fd, size_t idx ) const
{
2018-08-05 00:09:59 +00:00
if( fd.continuous )
{
2018-08-05 00:09:59 +00:00
if( idx < fd.frames.size() - 1 )
{
return fd.frames[idx+1].start;
}
else
{
return m_data.lastTime;
}
}
else
{
2018-08-05 00:09:59 +00:00
if( fd.frames[idx].end >= 0 )
{
return fd.frames[idx].end;
}
else
{
return m_data.lastTime;
}
}
}
2019-06-06 19:48:01 +00:00
const FrameImage* Worker::GetFrameImage( const FrameData& fd, size_t idx ) const
{
assert( idx < fd.frames.size() );
const auto& v = fd.frames[idx].frameImage;
if( v < 0 ) return nullptr;
return m_data.frameImage[v];
}
2019-06-22 12:05:18 +00:00
std::pair<int, int> Worker::GetFrameRange( const FrameData& fd, int64_t from, int64_t to )
{
2018-08-05 00:09:59 +00:00
auto zitbegin = std::lower_bound( fd.frames.begin(), fd.frames.end(), from, [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs; } );
2018-08-04 21:19:35 +00:00
if( zitbegin == fd.frames.end() ) zitbegin--;
2018-08-05 00:09:59 +00:00
const auto zitend = std::lower_bound( zitbegin, fd.frames.end(), to, [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs; } );
2018-08-04 17:47:09 +00:00
int zbegin = std::distance( fd.frames.begin(), zitbegin );
2018-08-05 00:09:59 +00:00
if( zbegin > 0 && zitbegin->start != from ) --zbegin;
2018-08-04 17:47:09 +00:00
const int zend = std::distance( fd.frames.begin(), zitend );
return std::make_pair( zbegin, zend );
}
const CallstackFrameData* Worker::GetCallstackFrame( const CallstackFrameId& ptr ) const
2018-06-19 23:18:59 +00:00
{
auto it = m_data.callstackFrameMap.find( ptr );
if( it == m_data.callstackFrameMap.end() )
{
return nullptr;
}
else
{
return it->second;
}
}
2018-03-23 00:50:38 +00:00
int64_t Worker::GetZoneEnd( const ZoneEvent& ev )
{
auto ptr = &ev;
for(;;)
{
if( ptr->End() >= 0 ) return ptr->End();
if( ptr->Child() < 0 ) return ptr->Start();
2019-11-10 00:43:28 +00:00
auto& children = GetZoneChildren( ptr->Child() );
if( children.is_magic() )
{
auto& c = *(Vector<ZoneEvent>*)&children;
ptr = &c.back();
}
else
{
ptr = children.back();
}
}
}
2018-03-23 00:50:38 +00:00
int64_t Worker::GetZoneEnd( const GpuEvent& ev )
{
auto ptr = &ev;
for(;;)
{
if( ptr->GpuEnd() >= 0 ) return ptr->GpuEnd();
if( ptr->Child() < 0 ) return ptr->GpuStart() >= 0 ? ptr->GpuStart() : m_data.lastTime;
2019-11-10 00:43:28 +00:00
auto& children = GetGpuChildren( ptr->Child() );
if( children.is_magic() )
{
auto& c = *(Vector<GpuEvent>*)&children;
ptr = &c.back();
}
else
{
ptr = children.back();
}
}
}
const char* Worker::GetString( uint64_t ptr ) const
{
const auto it = m_data.strings.find( ptr );
if( it == m_data.strings.end() || it->second == nullptr )
{
return "???";
}
else
{
return it->second;
}
}
const char* Worker::GetString( const StringRef& ref ) const
{
if( ref.isidx )
{
assert( ref.active );
2018-03-04 16:52:51 +00:00
return m_data.stringData[ref.str];
}
else
{
if( ref.active )
{
2018-03-04 16:52:51 +00:00
return GetString( ref.str );
}
else
{
return "???";
}
}
}
const char* Worker::GetString( const StringIdx& idx ) const
{
assert( idx.Active() );
return m_data.stringData[idx.Idx()];
}
static const char* BadExternalThreadNames[] = {
"ntdll.dll",
nullptr
};
const char* Worker::GetThreadName( uint64_t id ) const
{
const auto it = m_data.threadNames.find( id );
if( it == m_data.threadNames.end() )
{
const auto eit = m_data.externalNames.find( id );
if( eit == m_data.externalNames.end() )
{
return "???";
}
else
{
return eit->second.second;
}
}
else
{
// Client should send additional information about thread name, to make this check unnecessary
const auto txt = it->second;
if( txt[0] >= '0' && txt[0] <= '9' && atoi( txt ) == id )
{
const auto eit = m_data.externalNames.find( id );
if( eit != m_data.externalNames.end() )
{
const char* ext = eit->second.second;
const char** ptr = BadExternalThreadNames;
while( *ptr )
{
if( strcmp( *ptr, ext ) == 0 ) return txt;
ptr++;
}
return ext;
}
}
return txt;
}
}
bool Worker::IsThreadLocal( uint64_t id ) const
{
return m_data.localThreadCompress.Exists( id );
}
const SourceLocation& Worker::GetSourceLocation( int16_t srcloc ) const
{
if( srcloc < 0 )
{
return *m_data.sourceLocationPayload[-srcloc-1];
}
else
{
const auto it = m_data.sourceLocation.find( m_data.sourceLocationExpand[srcloc] );
assert( it != m_data.sourceLocation.end() );
return it->second;
}
}
2019-08-16 17:49:16 +00:00
std::pair<const char*, const char*> Worker::GetExternalName( uint64_t id ) const
{
const auto it = m_data.externalNames.find( id );
if( it == m_data.externalNames.end() )
{
2019-08-16 17:49:16 +00:00
return std::make_pair( "???", "???" );
}
else
{
return it->second;
}
}
const char* Worker::GetZoneName( const SourceLocation& srcloc ) const
{
if( srcloc.name.active )
{
return GetString( srcloc.name );
}
else
{
return GetString( srcloc.function );
}
}
const char* Worker::GetZoneName( const ZoneEvent& ev ) const
{
auto& srcloc = GetSourceLocation( ev.SrcLoc() );
return GetZoneName( ev, srcloc );
}
const char* Worker::GetZoneName( const ZoneEvent& ev, const SourceLocation& srcloc ) const
{
if( ev.name.Active() )
2018-06-29 14:12:40 +00:00
{
return GetString( ev.name );
}
else if( srcloc.name.active )
{
return GetString( srcloc.name );
}
else
{
return GetString( srcloc.function );
}
}
const char* Worker::GetZoneName( const GpuEvent& ev ) const
{
auto& srcloc = GetSourceLocation( ev.SrcLoc() );
return GetZoneName( ev, srcloc );
}
const char* Worker::GetZoneName( const GpuEvent& ev, const SourceLocation& srcloc ) const
{
if( srcloc.name.active )
{
return GetString( srcloc.name );
}
else
{
return GetString( srcloc.function );
}
}
2018-12-18 15:52:05 +00:00
static bool strstr_nocase( const char* l, const char* r )
{
const auto lsz = strlen( l );
const auto rsz = strlen( r );
auto ll = (char*)alloca( lsz + 1 );
2019-09-28 09:19:45 +00:00
auto rl = (char*)alloca( rsz + 1 );
2018-12-18 15:52:05 +00:00
for( size_t i=0; i<lsz; i++ )
{
ll[i] = tolower( l[i] );
}
ll[lsz] = '\0';
for( size_t i=0; i<rsz; i++ )
{
rl[i] = tolower( r[i] );
}
rl[rsz] = '\0';
return strstr( ll, rl ) != nullptr;
}
std::vector<int16_t> Worker::GetMatchingSourceLocation( const char* query, bool ignoreCase ) const
{
std::vector<int16_t> match;
const auto sz = m_data.sourceLocationExpand.size();
for( size_t i=1; i<sz; i++ )
{
const auto it = m_data.sourceLocation.find( m_data.sourceLocationExpand[i] );
assert( it != m_data.sourceLocation.end() );
const auto& srcloc = it->second;
const auto str = GetString( srcloc.name.active ? srcloc.name : srcloc.function );
bool found = false;
if( ignoreCase )
{
found = strstr_nocase( str, query );
}
else
{
found = strstr( str, query ) != nullptr;
}
if( found )
{
match.push_back( (int16_t)i );
}
}
for( auto& srcloc : m_data.sourceLocationPayload )
{
const auto str = GetString( srcloc->name.active ? srcloc->name : srcloc->function );
bool found = false;
if( ignoreCase )
{
found = strstr_nocase( str, query );
}
else
{
found = strstr( str, query ) != nullptr;
}
if( found )
{
auto it = m_data.sourceLocationPayloadMap.find( (const SourceLocation*)srcloc );
assert( it != m_data.sourceLocationPayloadMap.end() );
match.push_back( -int16_t( it->second + 1 ) );
}
}
return match;
}
#ifndef TRACY_NO_STATISTICS
const Worker::SourceLocationZones& Worker::GetZonesForSourceLocation( int16_t srcloc ) const
2018-03-18 01:35:39 +00:00
{
assert( AreSourceLocationZonesReady() );
2018-03-18 19:20:24 +00:00
static const SourceLocationZones empty;
2018-03-18 01:35:39 +00:00
auto it = m_data.sourceLocationZones.find( srcloc );
2018-03-18 19:20:24 +00:00
return it != m_data.sourceLocationZones.end() ? it->second : empty;
2018-03-18 01:35:39 +00:00
}
#endif
2018-03-18 01:35:39 +00:00
2019-10-28 21:45:10 +00:00
void Worker::Network()
{
auto ShouldExit = [this] { return m_shutdown.load( std::memory_order_relaxed ); };
auto lz4buf = std::make_unique<char[]>( LZ4Size );
for(;;)
{
{
std::unique_lock<std::mutex> lock( m_netWriteLock );
m_netWriteCv.wait( lock, [this] { return m_netWriteCnt > 0 || m_shutdown.load( std::memory_order_relaxed ); } );
if( m_shutdown.load( std::memory_order_relaxed ) ) goto close;
m_netWriteCnt--;
}
auto buf = m_buffer + m_bufferOffset;
lz4sz_t lz4sz;
if( !m_sock.Read( &lz4sz, sizeof( lz4sz ), 10, ShouldExit ) ) goto close;
if( !m_sock.Read( lz4buf.get(), lz4sz, 10, ShouldExit ) ) goto close;
m_bytes.fetch_add( sizeof( lz4sz ) + lz4sz, std::memory_order_relaxed );
auto sz = LZ4_decompress_safe_continue( (LZ4_streamDecode_t*)m_stream, lz4buf.get(), buf, lz4sz, TargetFrameSize );
assert( sz >= 0 );
m_decBytes.fetch_add( sz, std::memory_order_relaxed );
{
std::lock_guard<std::mutex> lock( m_netReadLock );
m_netRead.push_back( NetBuffer { m_bufferOffset, sz } );
m_netReadCv.notify_one();
}
m_bufferOffset += sz;
if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0;
}
close:
std::lock_guard<std::mutex> lock( m_netReadLock );
m_netRead.push_back( NetBuffer { -1 } );
m_netReadCv.notify_one();
2019-10-28 21:45:10 +00:00
}
void Worker::Exec()
{
2019-10-28 21:53:06 +00:00
auto ShouldExit = [this] { return m_shutdown.load( std::memory_order_relaxed ); };
for(;;)
{
2019-10-28 22:32:51 +00:00
if( m_shutdown.load( std::memory_order_relaxed ) ) { m_netWriteCv.notify_one(); return; };
if( m_sock.Connect( m_addr.c_str(), m_port ) ) break;
}
std::chrono::time_point<std::chrono::high_resolution_clock> t0;
m_sock.Send( HandshakeShibboleth, HandshakeShibbolethSize );
uint32_t protocolVersion = ProtocolVersion;
m_sock.Send( &protocolVersion, sizeof( protocolVersion ) );
HandshakeStatus handshake;
if( !m_sock.Read( &handshake, sizeof( handshake ), 10, ShouldExit ) )
{
m_handshake.store( HandshakeDropped, std::memory_order_relaxed );
goto close;
}
m_handshake.store( handshake, std::memory_order_relaxed );
switch( handshake )
{
case HandshakeWelcome:
break;
case HandshakeProtocolMismatch:
case HandshakeNotAvailable:
default:
goto close;
}
m_data.framesBase = m_data.frames.Retrieve( 0, [this] ( uint64_t name ) {
auto fd = m_slab.AllocInit<FrameData>();
fd->name = name;
fd->continuous = 1;
return fd;
}, [this] ( uint64_t name ) {
assert( name == 0 );
char tmp[6] = "Frame";
HandleFrameName( name, tmp, 5 );
} );
{
WelcomeMessage welcome;
if( !m_sock.Read( &welcome, sizeof( welcome ), 10, ShouldExit ) )
{
m_handshake.store( HandshakeDropped, std::memory_order_relaxed );
goto close;
}
m_timerMul = welcome.timerMul;
2019-08-15 15:52:36 +00:00
m_data.baseTime = welcome.initBegin;
const auto initEnd = TscTime( welcome.initEnd - m_data.baseTime );
m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );
2019-06-06 19:44:48 +00:00
m_data.framesBase->frames.push_back( FrameEvent{ initEnd, -1, -1 } );
m_data.lastTime = initEnd;
m_delay = TscTime( welcome.delay );
m_resolution = TscTime( welcome.resolution );
2019-08-17 20:19:04 +00:00
m_pid = welcome.pid;
m_onDemand = welcome.onDemand;
m_captureProgram = welcome.programName;
m_captureTime = welcome.epoch;
m_ignoreMemFreeFaults = welcome.onDemand || welcome.isApple;
char dtmp[64];
time_t date = welcome.epoch;
auto lt = localtime( &date );
strftime( dtmp, 64, "%F %T", lt );
char tmp[1024];
sprintf( tmp, "%s @ %s", welcome.programName, dtmp );
m_captureName = tmp;
m_hostInfo = welcome.hostInfo;
2018-08-04 17:47:09 +00:00
if( welcome.onDemand != 0 )
{
OnDemandPayloadMessage onDemand;
if( !m_sock.Read( &onDemand, sizeof( onDemand ), 10, ShouldExit ) )
{
m_handshake.store( HandshakeDropped, std::memory_order_relaxed );
goto close;
}
m_data.frameOffset = onDemand.frames;
2019-08-15 15:52:36 +00:00
m_data.framesBase->frames.push_back( FrameEvent{ TscTime( onDemand.currentTime - m_data.baseTime ), -1, -1 } );
}
}
m_serverQuerySpaceLeft = ( m_sock.GetSendBufSize() / ServerQueryPacketSize ) - ServerQueryPacketSize; // leave space for terminate request
m_hasData.store( true, std::memory_order_release );
LZ4_setStreamDecode( (LZ4_streamDecode_t*)m_stream, nullptr, 0 );
m_connected.store( true, std::memory_order_relaxed );
{
std::lock_guard<std::mutex> lock( m_netWriteLock );
m_netWriteCnt = 2;
m_netWriteCv.notify_one();
}
t0 = std::chrono::high_resolution_clock::now();
for(;;)
{
if( m_shutdown.load( std::memory_order_relaxed ) )
{
QueryTerminate();
2019-10-28 21:52:52 +00:00
goto close;
}
NetBuffer netbuf;
{
std::unique_lock<std::mutex> lock( m_netReadLock );
m_netReadCv.wait( lock, [this] { return !m_netRead.empty(); } );
netbuf = m_netRead.front();
m_netRead.erase( m_netRead.begin() );
}
if( netbuf.bufferOffset < 0 ) goto close;
const char* ptr = m_buffer + netbuf.bufferOffset;
const char* end = ptr + netbuf.size;
{
std::lock_guard<std::shared_mutex> lock( m_data.lock );
while( ptr < end )
{
auto ev = (const QueueItem*)ptr;
if( !DispatchProcess( *ev, ptr ) )
{
QueryTerminate();
goto close;
}
}
{
std::lock_guard<std::mutex> lock( m_netWriteLock );
m_netWriteCnt++;
m_netWriteCv.notify_one();
}
HandlePostponedPlots();
while( !m_serverQueryQueue.empty() && m_serverQuerySpaceLeft > 0 )
{
m_serverQuerySpaceLeft--;
const auto& query = m_serverQueryQueue.back();
m_sock.Send( &query, ServerQueryPacketSize );
m_serverQueryQueue.pop_back();
}
}
auto t1 = std::chrono::high_resolution_clock::now();
auto td = std::chrono::duration_cast<std::chrono::milliseconds>( t1 - t0 ).count();
enum { MbpsUpdateTime = 200 };
if( td > MbpsUpdateTime )
{
const auto bytes = m_bytes.exchange( 0, std::memory_order_relaxed );
const auto decBytes = m_decBytes.exchange( 0, std::memory_order_relaxed );
std::lock_guard<std::shared_mutex> lock( m_mbpsData.lock );
m_mbpsData.mbps.erase( m_mbpsData.mbps.begin() );
m_mbpsData.mbps.emplace_back( bytes / ( td * 125.f ) );
m_mbpsData.compRatio = float( bytes ) / decBytes;
2019-04-01 17:55:37 +00:00
m_mbpsData.queue = m_serverQueryQueue.size();
2019-10-23 22:47:16 +00:00
m_mbpsData.transferred += bytes;
t0 = t1;
}
if( m_terminate )
{
if( m_pendingStrings != 0 || m_pendingThreads != 0 || m_pendingSourceLocation != 0 || m_pendingCallstackFrames != 0 ||
2019-06-06 19:39:54 +00:00
!m_pendingCustomStrings.empty() || m_data.plots.IsPending() || m_pendingCallstackPtr != 0 ||
m_pendingExternalNames != 0 || m_pendingCallstackSubframes != 0 || !m_pendingFrameImageData.empty() )
{
continue;
}
2019-08-01 21:14:09 +00:00
if( !m_crashed && !m_disconnect )
{
bool done = true;
for( auto& v : m_data.threads )
{
if( !v->stack.empty() )
{
done = false;
break;
}
}
if( !done ) continue;
}
2019-04-01 16:52:32 +00:00
Query( ServerQueryTerminate, 0 );
break;
}
}
close:
Shutdown();
m_netWriteCv.notify_one();
m_sock.Close();
m_connected.store( false, std::memory_order_relaxed );
}
2019-04-01 16:52:32 +00:00
void Worker::Query( ServerQuery type, uint64_t data )
{
ServerQueryPacket query { type, data };
if( m_serverQuerySpaceLeft > 0 )
{
m_serverQuerySpaceLeft--;
m_sock.Send( &query, ServerQueryPacketSize );
}
else
{
m_serverQueryQueue.insert( m_serverQueryQueue.begin(), query );
}
}
void Worker::QueryTerminate()
{
ServerQueryPacket query { ServerQueryTerminate, 0 };
m_sock.Send( &query, ServerQueryPacketSize );
}
bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )
{
if( ev.hdr.idx >= (int)QueueType::StringData )
{
ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );
2019-06-06 19:39:54 +00:00
if( ev.hdr.type == QueueType::FrameImageData )
{
2019-06-06 19:39:54 +00:00
uint32_t sz;
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
AddFrameImageData( ev.stringTransfer.ptr, ptr, sz );
ptr += sz;
}
else
{
uint16_t sz;
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
switch( ev.hdr.type )
{
case QueueType::CustomStringData:
AddCustomString( ev.stringTransfer.ptr, ptr, sz );
break;
case QueueType::StringData:
AddString( ev.stringTransfer.ptr, ptr, sz );
m_serverQuerySpaceLeft++;
break;
case QueueType::ThreadName:
AddThreadString( ev.stringTransfer.ptr, ptr, sz );
m_serverQuerySpaceLeft++;
break;
case QueueType::PlotName:
HandlePlotName( ev.stringTransfer.ptr, ptr, sz );
m_serverQuerySpaceLeft++;
break;
case QueueType::SourceLocationPayload:
AddSourceLocationPayload( ev.stringTransfer.ptr, ptr, sz );
break;
case QueueType::CallstackPayload:
AddCallstackPayload( ev.stringTransfer.ptr, ptr, sz );
break;
case QueueType::FrameName:
HandleFrameName( ev.stringTransfer.ptr, ptr, sz );
m_serverQuerySpaceLeft++;
break;
case QueueType::CallstackAllocPayload:
AddCallstackAllocPayload( ev.stringTransfer.ptr, ptr, sz );
break;
case QueueType::ExternalName:
AddExternalName( ev.stringTransfer.ptr, ptr, sz );
break;
2019-08-16 17:49:16 +00:00
case QueueType::ExternalThreadName:
AddExternalThreadName( ev.stringTransfer.ptr, ptr, sz );
break;
2019-06-06 19:39:54 +00:00
default:
assert( false );
break;
}
ptr += sz;
}
2019-01-14 22:08:34 +00:00
return true;
}
else
{
ptr += QueueDataSize[ev.hdr.idx];
2019-01-14 22:08:34 +00:00
return Process( ev );
}
}
void Worker::CheckSourceLocation( uint64_t ptr )
{
if( m_data.checkSrclocLast != ptr )
{
m_data.checkSrclocLast = ptr;
if( m_data.sourceLocation.find( ptr ) == m_data.sourceLocation.end() )
{
NewSourceLocation( ptr );
}
}
}
void Worker::NewSourceLocation( uint64_t ptr )
{
static const SourceLocation emptySourceLocation = {};
m_data.sourceLocation.emplace( ptr, emptySourceLocation );
m_pendingSourceLocation++;
m_sourceLocationQueue.push_back( ptr );
2019-04-01 16:52:32 +00:00
Query( ServerQuerySourceLocation, ptr );
}
2019-10-25 19:07:28 +00:00
int16_t Worker::ShrinkSourceLocationReal( uint64_t srcloc )
{
auto it = m_sourceLocationShrink.find( srcloc );
if( it != m_sourceLocationShrink.end() )
{
2019-10-25 19:07:28 +00:00
m_data.shrinkSrclocLast.first = srcloc;
m_data.shrinkSrclocLast.second = it->second;
return it->second;
}
else
{
return NewShrinkedSourceLocation( srcloc );
}
}
int16_t Worker::NewShrinkedSourceLocation( uint64_t srcloc )
{
assert( m_data.sourceLocationExpand.size() < std::numeric_limits<int16_t>::max() );
const auto sz = int16_t( m_data.sourceLocationExpand.size() );
m_data.sourceLocationExpand.push_back( srcloc );
#ifndef TRACY_NO_STATISTICS
auto res = m_data.sourceLocationZones.emplace( sz, SourceLocationZones() );
m_data.srclocZonesLast.first = sz;
m_data.srclocZonesLast.second = &res.first->second;
2018-07-29 12:16:13 +00:00
#else
auto res = m_data.sourceLocationZonesCnt.emplace( sz, 0 );
m_data.srclocCntLast.first = sz;
m_data.srclocCntLast.second = &res.first->second;
#endif
m_sourceLocationShrink.emplace( srcloc, sz );
2019-10-25 19:07:28 +00:00
m_data.shrinkSrclocLast.first = srcloc;
m_data.shrinkSrclocLast.second = sz;
return sz;
}
void Worker::InsertMessageData( MessageData* msg )
{
if( m_data.messages.empty() )
{
m_data.messages.push_back( msg );
}
else if( m_data.messages.back()->time < msg->time )
{
m_data.messages.push_back_non_empty( msg );
}
else
{
auto mit = std::lower_bound( m_data.messages.begin(), m_data.messages.end(), msg->time, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );
m_data.messages.insert( mit, msg );
}
auto td = m_threadCtxData;
if( !td ) td = m_threadCtxData = NoticeThread( m_threadCtx );
auto vec = &td->messages;
if( vec->empty() )
{
vec->push_back( msg );
}
else if( vec->back()->time < msg->time )
{
vec->push_back_non_empty( msg );
}
else
{
auto tmit = std::lower_bound( vec->begin(), vec->end(), msg->time, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );
vec->insert( tmit, msg );
}
}
2019-08-03 12:35:01 +00:00
ThreadData* Worker::NoticeThreadReal( uint64_t thread )
{
auto it = m_threadMap.find( thread );
if( it != m_threadMap.end() )
{
2019-08-03 12:35:01 +00:00
m_data.threadDataLast.first = thread;
m_data.threadDataLast.second = it->second;
return it->second;
}
else
{
return NewThread( thread );
}
}
2019-10-24 20:33:48 +00:00
ThreadData* Worker::RetrieveThreadReal( uint64_t thread )
{
auto it = m_threadMap.find( thread );
if( it != m_threadMap.end() )
{
m_data.threadDataLast.first = thread;
m_data.threadDataLast.second = it->second;
return it->second;
}
else
{
return nullptr;
}
}
#ifndef TRACY_NO_STATISTICS
Worker::SourceLocationZones* Worker::GetSourceLocationZonesReal( uint16_t srcloc )
{
auto it = m_data.sourceLocationZones.find( srcloc );
assert( it != m_data.sourceLocationZones.end() );
m_data.srclocZonesLast.first = srcloc;
m_data.srclocZonesLast.second = &it->second;
return &it->second;
}
#else
uint64_t* Worker::GetSourceLocationZonesCntReal( uint16_t srcloc )
{
auto it = m_data.sourceLocationZonesCnt.find( srcloc );
assert( it != m_data.sourceLocationZonesCnt.end() );
m_data.srclocCntLast.first = srcloc;
m_data.srclocCntLast.second = &it->second;
return &it->second;
}
#endif
2019-09-08 12:07:16 +00:00
const ThreadData* Worker::GetThreadData( uint64_t tid ) const
{
auto it = m_threadMap.find( tid );
if( it == m_threadMap.end() ) return nullptr;
return it->second;
}
ThreadData* Worker::NewThread( uint64_t thread )
{
CheckThreadString( thread );
auto td = m_slab.AllocInit<ThreadData>();
td->id = thread;
td->count = 0;
2019-01-14 21:56:10 +00:00
td->nextZoneId = 0;
m_data.threads.push_back( td );
m_threadMap.emplace( thread, td );
2019-08-03 12:35:01 +00:00
m_data.threadDataLast.first = thread;
m_data.threadDataLast.second = td;
return td;
}
void Worker::NewZone( ZoneEvent* zone, uint64_t thread )
{
m_data.zonesCnt++;
2018-03-18 01:05:33 +00:00
#ifndef TRACY_NO_STATISTICS
auto slz = GetSourceLocationZones( zone->SrcLoc() );
auto& ztd = slz->zones.push_next();
ztd.SetZone( zone );
ztd.SetThread( CompressThread( thread ) );
2018-07-29 12:16:13 +00:00
#else
2019-11-08 22:59:20 +00:00
CountZoneStatistics( zone );
#endif
2018-03-18 01:05:33 +00:00
auto td = m_threadCtxData;
if( !td ) td = m_threadCtxData = NoticeThread( thread );
td->count++;
if( td->stack.empty() )
{
td->stack.push_back( zone );
td->timeline.push_back( zone );
}
else
{
2019-11-10 16:48:54 +00:00
auto& back = td->stack.back();
2019-10-24 22:43:44 +00:00
const auto backChild = back->Child();
if( backChild < 0 )
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
{
back->SetChild( int32_t( m_data.zoneChildren.size() ) );
if( m_data.zoneVectorCache.empty() )
{
2019-11-02 15:17:20 +00:00
m_data.zoneChildren.push_back( Vector<short_ptr<ZoneEvent>>( zone ) );
}
else
{
2019-11-02 15:17:20 +00:00
Vector<short_ptr<ZoneEvent>> vze = std::move( m_data.zoneVectorCache.back_and_pop() );
assert( !vze.empty() );
vze.clear();
vze.push_back_non_empty( zone );
m_data.zoneChildren.push_back( std::move( vze ) );
}
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
}
else
{
2019-10-24 22:51:01 +00:00
assert( !m_data.zoneChildren[backChild].empty() );
m_data.zoneChildren[backChild].push_back_non_empty( zone );
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
}
td->stack.push_back_non_empty( zone );
}
2019-01-14 22:08:34 +00:00
td->zoneIdStack.push_back( td->nextZoneId );
td->nextZoneId = 0;
#ifndef TRACY_NO_STATISTICS
td->childTimeStack.push_back( 0 );
#endif
}
void Worker::InsertLockEvent( LockMap& lockmap, LockEvent* lev, uint64_t thread, int64_t time )
{
if( m_data.lastTime < time ) m_data.lastTime = time;
NoticeThread( thread );
auto it = lockmap.threadMap.find( thread );
if( it == lockmap.threadMap.end() )
{
assert( lockmap.threadList.size() < MaxLockThreads );
it = lockmap.threadMap.emplace( thread, lockmap.threadList.size() ).first;
lockmap.threadList.emplace_back( thread );
}
lev->thread = it->second;
assert( lev->thread == it->second );
auto& timeline = lockmap.timeline;
if( timeline.empty() )
{
timeline.push_back( { lev } );
UpdateLockCount( lockmap, timeline.size() - 1 );
}
else
{
2019-10-24 23:00:32 +00:00
assert( timeline.back().ptr->Time() <= time );
timeline.push_back_non_empty( { lev } );
UpdateLockCount( lockmap, timeline.size() - 1 );
}
auto& range = lockmap.range[it->second];
if( range.start > time ) range.start = time;
if( range.end < time ) range.end = time;
}
void Worker::CheckString( uint64_t ptr )
{
if( ptr == 0 ) return;
if( m_data.strings.find( ptr ) != m_data.strings.end() ) return;
m_data.strings.emplace( ptr, "???" );
m_pendingStrings++;
2019-04-01 16:52:32 +00:00
Query( ServerQueryString, ptr );
}
void Worker::CheckThreadString( uint64_t id )
{
if( m_data.threadNames.find( id ) != m_data.threadNames.end() ) return;
m_data.threadNames.emplace( id, "???" );
m_pendingThreads++;
2019-04-01 16:52:32 +00:00
Query( ServerQueryThreadString, id );
}
void Worker::CheckExternalName( uint64_t id )
{
if( m_data.externalNames.find( id ) != m_data.externalNames.end() ) return;
2019-08-16 17:49:16 +00:00
m_data.externalNames.emplace( id, std::make_pair( "???", "???" ) );
m_pendingExternalNames += 2;
Query( ServerQueryExternalName, id );
}
void Worker::AddSourceLocation( const QueueSourceLocation& srcloc )
{
assert( m_pendingSourceLocation > 0 );
m_pendingSourceLocation--;
const auto ptr = m_sourceLocationQueue.front();
m_sourceLocationQueue.erase( m_sourceLocationQueue.begin() );
auto it = m_data.sourceLocation.find( ptr );
assert( it != m_data.sourceLocation.end() );
CheckString( srcloc.name );
CheckString( srcloc.file );
CheckString( srcloc.function );
2019-05-10 18:20:08 +00:00
const uint32_t color = ( srcloc.r << 16 ) | ( srcloc.g << 8 ) | srcloc.b;
it->second = SourceLocation { srcloc.name == 0 ? StringRef() : StringRef( StringRef::Ptr, srcloc.name ), StringRef( StringRef::Ptr, srcloc.function ), StringRef( StringRef::Ptr, srcloc.file ), srcloc.line, color };
}
void Worker::AddSourceLocationPayload( uint64_t ptr, const char* data, size_t sz )
{
const auto start = data;
assert( m_pendingSourceLocationPayload.find( ptr ) == m_pendingSourceLocationPayload.end() );
uint32_t color, line;
memcpy( &color, data, 4 );
memcpy( &line, data + 4, 4 );
data += 8;
auto end = data;
while( *end ) end++;
const auto func = StoreString( data, end - data );
end++;
data = end;
while( *end ) end++;
const auto source = StoreString( data, end - data );
end++;
const auto nsz = sz - ( end - start );
color = ( ( color & 0x00FF0000 ) >> 16 ) |
( ( color & 0x0000FF00 ) ) |
( ( color & 0x000000FF ) << 16 );
SourceLocation srcloc { nsz == 0 ? StringRef() : StringRef( StringRef::Idx, StoreString( end, nsz ).idx ), StringRef( StringRef::Idx, func.idx ), StringRef( StringRef::Idx, source.idx ), line, color };
auto it = m_data.sourceLocationPayloadMap.find( &srcloc );
if( it == m_data.sourceLocationPayloadMap.end() )
{
auto slptr = m_slab.Alloc<SourceLocation>();
memcpy( slptr, &srcloc, sizeof( srcloc ) );
uint32_t idx = m_data.sourceLocationPayload.size();
m_data.sourceLocationPayloadMap.emplace( slptr, idx );
m_pendingSourceLocationPayload.emplace( ptr, -int16_t( idx + 1 ) );
m_data.sourceLocationPayload.push_back( slptr );
const auto key = -int16_t( idx + 1 );
#ifndef TRACY_NO_STATISTICS
auto res = m_data.sourceLocationZones.emplace( key, SourceLocationZones() );
m_data.srclocZonesLast.first = key;
m_data.srclocZonesLast.second = &res.first->second;
2018-07-29 12:16:13 +00:00
#else
auto res = m_data.sourceLocationZonesCnt.emplace( key, 0 );
m_data.srclocCntLast.first = key;
m_data.srclocCntLast.second = &res.first->second;
#endif
}
else
{
m_pendingSourceLocationPayload.emplace( ptr, -int16_t( it->second + 1 ) );
}
}
void Worker::AddString( uint64_t ptr, const char* str, size_t sz )
{
assert( m_pendingStrings > 0 );
m_pendingStrings--;
auto it = m_data.strings.find( ptr );
assert( it != m_data.strings.end() && strcmp( it->second, "???" ) == 0 );
const auto sl = StoreString( str, sz );
it->second = sl.ptr;
}
void Worker::AddThreadString( uint64_t id, const char* str, size_t sz )
{
assert( m_pendingThreads > 0 );
m_pendingThreads--;
auto it = m_data.threadNames.find( id );
assert( it != m_data.threadNames.end() && strcmp( it->second, "???" ) == 0 );
const auto sl = StoreString( str, sz );
it->second = sl.ptr;
}
void Worker::AddCustomString( uint64_t ptr, const char* str, size_t sz )
{
assert( m_pendingCustomStrings.find( ptr ) == m_pendingCustomStrings.end() );
m_pendingCustomStrings.emplace( ptr, StoreString( str, sz ) );
}
void Worker::AddExternalName( uint64_t ptr, const char* str, size_t sz )
{
assert( m_pendingExternalNames > 0 );
m_pendingExternalNames--;
auto it = m_data.externalNames.find( ptr );
2019-08-16 17:49:16 +00:00
assert( it != m_data.externalNames.end() && strcmp( it->second.first, "???" ) == 0 );
const auto sl = StoreString( str, sz );
2019-08-16 17:49:16 +00:00
it->second.first = sl.ptr;
}
void Worker::AddExternalThreadName( uint64_t ptr, const char* str, size_t sz )
2019-08-16 17:49:16 +00:00
{
assert( m_pendingExternalNames > 0 );
m_pendingExternalNames--;
auto it = m_data.externalNames.find( ptr );
assert( it != m_data.externalNames.end() && strcmp( it->second.second, "???" ) == 0 );
const auto sl = StoreString( str, sz );
it->second.second = sl.ptr;
}
2019-07-19 19:46:58 +00:00
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,
101, 103, 102, 100, 109, 111, 110, 108, 105, 107, 106, 104, 97, 99, 98, 96,
69, 71, 70, 68, 77, 79, 78, 76, 73, 75, 74, 72, 65, 67, 66, 64,
213, 215, 214, 212, 221, 223, 222, 220, 217, 219, 218, 216, 209, 211, 210, 208,
245, 247, 246, 244, 253, 255, 254, 252, 249, 251, 250, 248, 241, 243, 242, 240,
229, 231, 230, 228, 237, 239, 238, 236, 233, 235, 234, 232, 225, 227, 226, 224,
197, 199, 198, 196, 205, 207, 206, 204, 201, 203, 202, 200, 193, 195, 194, 192,
149, 151, 150, 148, 157, 159, 158, 156, 153, 155, 154, 152, 145, 147, 146, 144,
181, 183, 182, 180, 189, 191, 190, 188, 185, 187, 186, 184, 177, 179, 178, 176,
165, 167, 166, 164, 173, 175, 174, 172, 169, 171, 170, 168, 161, 163, 162, 160,
133, 135, 134, 132, 141, 143, 142, 140, 137, 139, 138, 136, 129, 131, 130, 128,
21, 23, 22, 20, 29, 31, 30, 28, 25, 27, 26, 24, 17, 19, 18, 16,
53, 55, 54, 52, 61, 63, 62, 60, 57, 59, 58, 56, 49, 51, 50, 48,
37, 39, 38, 36, 45, 47, 46, 44, 41, 43, 42, 40, 33, 35, 34, 32,
5, 7, 6, 4, 13, 15, 14, 12, 9, 11, 10, 8, 1, 3, 2, 0
};
void Worker::AddFrameImageData( uint64_t ptr, const char* data, size_t sz )
2019-06-06 19:39:54 +00:00
{
assert( m_pendingFrameImageData.find( ptr ) == m_pendingFrameImageData.end() );
2019-07-19 19:46:58 +00:00
assert( sz % 8 == 0 );
// Input data buffer cannot be changed, as it is used as LZ4 dictionary.
if( m_frameImageBufferSize < sz )
{
m_frameImageBufferSize = sz;
delete[] m_frameImageBuffer;
m_frameImageBuffer = new char[sz];
}
auto src = (uint8_t*)data;
auto dst = (uint8_t*)m_frameImageBuffer;
2019-07-19 19:46:58 +00:00
for( size_t i=0; i<sz; i+=8 )
{
memcpy( dst, src, 4 );
for( int j=4; j<8; j++ ) dst[j] = DxtcIndexTable[src[j]];
src += 8;
dst += 8;
2019-07-19 19:46:58 +00:00
}
uint32_t csz;
auto image = PackFrameImage( m_frameImageBuffer, sz, csz );
m_pendingFrameImageData.emplace( ptr, FrameImagePending { image, csz } );
2019-06-06 19:39:54 +00:00
}
uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const
{
assert( id.sel == 0 );
return ( id.idx & 0x7FFFFFFFFFFFFFFF ) | ( ( id.idx & 0x4000000000000000 ) << 1 );
}
void Worker::AddCallstackPayload( uint64_t ptr, const char* _data, size_t _sz )
2018-06-19 19:15:36 +00:00
{
assert( m_pendingCallstackPtr == 0 );
2018-06-19 19:15:36 +00:00
const auto sz = _sz / sizeof( uint64_t );
const auto memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );
2018-06-19 19:15:36 +00:00
auto mem = (char*)m_slab.AllocRaw( memsize );
auto data = (CallstackFrameId*)mem;
auto dst = data;
auto src = (uint64_t*)_data;
for( size_t i=0; i<sz; i++ )
{
*dst++ = PackPointer( *src++ );
}
2018-06-19 19:15:36 +00:00
auto arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );
new(arr) VarArray<CallstackFrameId>( sz, data );
2018-06-19 19:15:36 +00:00
2019-03-03 16:34:56 +00:00
uint32_t idx;
auto it = m_data.callstackMap.find( arr );
if( it == m_data.callstackMap.end() )
{
idx = m_data.callstackPayload.size();
m_data.callstackMap.emplace( arr, idx );
m_data.callstackPayload.push_back( arr );
for( auto& frame : *arr )
{
auto fit = m_data.callstackFrameMap.find( frame );
if( fit == m_data.callstackFrameMap.end() )
{
m_pendingCallstackFrames++;
2019-04-01 16:52:32 +00:00
Query( ServerQueryCallstackFrame, GetCanonicalPointer( frame ) );
2019-03-03 16:34:56 +00:00
}
}
}
else
{
idx = it->second;
m_slab.Unalloc( memsize );
}
m_pendingCallstackPtr = ptr;
m_pendingCallstackId = idx;
2019-03-03 16:34:56 +00:00
}
void Worker::AddCallstackAllocPayload( uint64_t ptr, const char* data, size_t _sz )
2019-03-03 16:34:56 +00:00
{
CallstackFrameId stack[64];
const auto sz = *(uint32_t*)data; data += 4;
assert( sz <= 64 );
for( uint32_t i=0; i<sz; i++ )
{
uint32_t sz;
CallstackFrame cf;
memcpy( &cf.line, data, 4 ); data += 4;
memcpy( &sz, data, 4 ); data += 4;
cf.name = StoreString( data, sz ).idx; data += sz;
memcpy( &sz, data, 4 ); data += 4;
cf.file = StoreString( data, sz ).idx; data += sz;
CallstackFrameData cfd = { &cf, 1 };
CallstackFrameId id;
auto it = m_data.revFrameMap.find( &cfd );
if( it == m_data.revFrameMap.end() )
{
auto frame = m_slab.Alloc<CallstackFrame>();
memcpy( frame, &cf, sizeof( CallstackFrame ) );
auto frameData = m_slab.Alloc<CallstackFrameData>();
frameData->data = frame;
frameData->size = 1;
id.idx = m_callstackAllocNextIdx++;
id.sel = 1;
m_data.callstackFrameMap.emplace( id, frameData );
m_data.revFrameMap.emplace( frameData, id );
}
else
{
id = it->second;
}
stack[i] = id;
}
VarArray<CallstackFrameId>* arr;
size_t memsize;
if( m_pendingCallstackPtr != 0 )
{
const auto nativeCs = m_data.callstackPayload[m_pendingCallstackId];
const auto nsz = nativeCs->size();
const auto tsz = sz + nsz;
memsize = sizeof( VarArray<CallstackFrameId> ) + tsz * sizeof( CallstackFrameId );
auto mem = (char*)m_slab.AllocRaw( memsize );
memcpy( mem, stack, sizeof( CallstackFrameId ) * sz );
memcpy( mem + sizeof( CallstackFrameId ) * sz, nativeCs->data(), sizeof( CallstackFrameId ) * nsz );
arr = (VarArray<CallstackFrameId>*)( mem + tsz * sizeof( CallstackFrameId ) );
new(arr) VarArray<CallstackFrameId>( tsz, (CallstackFrameId*)mem );
}
else
{
memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );
auto mem = (char*)m_slab.AllocRaw( memsize );
memcpy( mem, stack, sizeof( CallstackFrameId ) * sz );
2019-03-03 16:34:56 +00:00
arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );
new(arr) VarArray<CallstackFrameId>( sz, (CallstackFrameId*)mem );
}
2019-03-03 16:34:56 +00:00
2018-06-19 19:15:36 +00:00
uint32_t idx;
auto it = m_data.callstackMap.find( arr );
if( it == m_data.callstackMap.end() )
{
idx = m_data.callstackPayload.size();
m_data.callstackMap.emplace( arr, idx );
m_data.callstackPayload.push_back( arr );
2018-06-19 22:25:26 +00:00
for( auto& frame : *arr )
{
auto fit = m_data.callstackFrameMap.find( frame );
if( fit == m_data.callstackFrameMap.end() )
{
2018-06-20 21:42:00 +00:00
m_pendingCallstackFrames++;
2019-04-01 16:52:32 +00:00
Query( ServerQueryCallstackFrame, GetCanonicalPointer( frame ) );
2018-06-19 22:25:26 +00:00
}
}
2018-06-19 19:15:36 +00:00
}
else
{
idx = it->second;
m_slab.Unalloc( memsize );
}
m_pendingCallstackPtr = ptr;
m_pendingCallstackId = idx;
2018-06-19 19:15:36 +00:00
}
void Worker::InsertPlot( PlotData* plot, int64_t time, double val )
{
if( plot->data.empty() )
{
plot->min = val;
plot->max = val;
plot->data.push_back( { Int48( time ), val } );
}
else if( plot->data.back().time.Val() < time )
{
if( plot->min > val ) plot->min = val;
else if( plot->max < val ) plot->max = val;
plot->data.push_back_non_empty( { Int48( time ), val } );
}
else
{
if( plot->min > val ) plot->min = val;
else if( plot->max < val ) plot->max = val;
if( plot->postpone.empty() )
{
plot->postponeTime = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
plot->postpone.push_back( { Int48( time ), val } );
}
else
{
plot->postpone.push_back_non_empty( { Int48( time ), val } );
}
}
}
void Worker::HandlePlotName( uint64_t name, const char* str, size_t sz )
{
const auto sl = StoreString( str, sz );
m_data.plots.StringDiscovered( name, sl, m_data.strings, [this] ( PlotData* dst, PlotData* src ) {
2018-08-04 14:33:03 +00:00
for( auto& v : src->data )
{
InsertPlot( dst, v.time.Val(), v.val );
}
2018-08-04 14:33:03 +00:00
} );
}
void Worker::HandleFrameName( uint64_t name, const char* str, size_t sz )
2018-08-04 18:48:21 +00:00
{
const auto sl = StoreString( str, sz );
2019-01-06 20:11:36 +00:00
m_data.frames.StringDiscovered( name, sl, m_data.strings, [] ( FrameData* dst, FrameData* src ) {
2018-08-04 18:48:21 +00:00
auto sz = dst->frames.size();
dst->frames.insert( dst->frames.end(), src->frames.begin(), src->frames.end() );
2018-08-05 00:09:59 +00:00
std::inplace_merge( dst->frames.begin(), dst->frames.begin() + sz, dst->frames.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs.start; } );
2018-08-04 18:48:21 +00:00
} );
}
void Worker::HandlePostponedPlots()
{
2018-08-04 14:33:03 +00:00
for( auto& plot : m_data.plots.Data() )
{
auto& src = plot->postpone;
if( src.empty() ) continue;
if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count() - plot->postponeTime < 100 ) continue;
auto& dst = plot->data;
#ifdef MY_LIBCPP_SUCKS
pdqsort_branchless( src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
#else
std::sort( std::execution::par_unseq, src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
#endif
const auto ds = std::lower_bound( dst.begin(), dst.end(), src.front().time.Val(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
const auto dsd = std::distance( dst.begin(), ds ) ;
const auto de = std::lower_bound( ds, dst.end(), src.back().time.Val(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
const auto ded = std::distance( dst.begin(), de );
dst.insert( de, src.begin(), src.end() );
std::inplace_merge( dst.begin() + dsd, dst.begin() + ded, dst.begin() + ded + src.size(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
src.clear();
}
}
StringLocation Worker::StoreString( const char* str, size_t sz )
{
StringLocation ret;
2019-02-12 19:23:14 +00:00
charutil::StringKey key = { str, sz };
auto sit = m_data.stringMap.find( key );
if( sit == m_data.stringMap.end() )
{
auto ptr = m_slab.Alloc<char>( sz+1 );
2018-03-19 14:41:28 +00:00
memcpy( ptr, str, sz );
ptr[sz] = '\0';
ret.ptr = ptr;
ret.idx = m_data.stringData.size();
2019-02-12 19:23:14 +00:00
m_data.stringMap.emplace( charutil::StringKey { ptr, sz }, m_data.stringData.size() );
m_data.stringData.push_back( ptr );
}
else
{
2019-02-12 19:23:14 +00:00
ret.ptr = sit->first.ptr;
ret.idx = sit->second;
}
return ret;
}
2019-01-14 22:08:34 +00:00
bool Worker::Process( const QueueItem& ev )
{
switch( ev.hdr.type )
{
case QueueType::ThreadContext:
ProcessThreadContext( ev.threadCtx );
break;
case QueueType::ZoneBegin:
ProcessZoneBegin( ev.zoneBegin );
break;
case QueueType::ZoneBeginCallstack:
ProcessZoneBeginCallstack( ev.zoneBegin );
break;
case QueueType::ZoneBeginAllocSrcLoc:
ProcessZoneBeginAllocSrcLoc( ev.zoneBegin );
break;
case QueueType::ZoneBeginAllocSrcLocCallstack:
ProcessZoneBeginAllocSrcLocCallstack( ev.zoneBegin );
break;
case QueueType::ZoneEnd:
2019-01-15 17:55:21 +00:00
ProcessZoneEnd( ev.zoneEnd );
break;
2019-01-14 21:56:10 +00:00
case QueueType::ZoneValidation:
ProcessZoneValidation( ev.zoneValidation );
break;
case QueueType::FrameMarkMsg:
ProcessFrameMark( ev.frameMark );
break;
2018-08-05 00:09:59 +00:00
case QueueType::FrameMarkMsgStart:
ProcessFrameMarkStart( ev.frameMark );
break;
case QueueType::FrameMarkMsgEnd:
ProcessFrameMarkEnd( ev.frameMark );
break;
2019-06-06 19:39:54 +00:00
case QueueType::FrameImage:
ProcessFrameImage( ev.frameImage );
break;
case QueueType::SourceLocation:
AddSourceLocation( ev.srcloc );
2019-04-01 17:37:39 +00:00
m_serverQuerySpaceLeft++;
break;
case QueueType::ZoneText:
ProcessZoneText( ev.zoneText );
break;
2018-06-29 14:12:17 +00:00
case QueueType::ZoneName:
ProcessZoneName( ev.zoneText );
break;
case QueueType::LockAnnounce:
ProcessLockAnnounce( ev.lockAnnounce );
break;
case QueueType::LockTerminate:
ProcessLockTerminate( ev.lockTerminate );
break;
case QueueType::LockWait:
ProcessLockWait( ev.lockWait );
break;
case QueueType::LockObtain:
ProcessLockObtain( ev.lockObtain );
break;
case QueueType::LockRelease:
ProcessLockRelease( ev.lockRelease );
break;
case QueueType::LockSharedWait:
ProcessLockSharedWait( ev.lockWait );
break;
case QueueType::LockSharedObtain:
ProcessLockSharedObtain( ev.lockObtain );
break;
case QueueType::LockSharedRelease:
ProcessLockSharedRelease( ev.lockRelease );
break;
case QueueType::LockMark:
ProcessLockMark( ev.lockMark );
break;
case QueueType::PlotData:
ProcessPlotData( ev.plotData );
break;
case QueueType::PlotConfig:
ProcessPlotConfig( ev.plotConfig );
break;
case QueueType::Message:
ProcessMessage( ev.message );
break;
case QueueType::MessageLiteral:
ProcessMessageLiteral( ev.message );
break;
2019-05-10 18:17:44 +00:00
case QueueType::MessageColor:
ProcessMessageColor( ev.messageColor );
break;
case QueueType::MessageLiteralColor:
ProcessMessageLiteralColor( ev.messageColor );
break;
2019-11-14 23:42:44 +00:00
case QueueType::MessageCallstack:
ProcessMessageCallstack( ev.message );
break;
case QueueType::MessageLiteralCallstack:
ProcessMessageLiteralCallstack( ev.message );
break;
case QueueType::MessageColorCallstack:
ProcessMessageColorCallstack( ev.messageColor );
break;
case QueueType::MessageLiteralColorCallstack:
ProcessMessageLiteralColorCallstack( ev.messageColor );
break;
2019-07-12 16:30:45 +00:00
case QueueType::MessageAppInfo:
ProcessMessageAppInfo( ev.message );
break;
case QueueType::GpuNewContext:
ProcessGpuNewContext( ev.gpuNewContext );
break;
case QueueType::GpuZoneBegin:
ProcessGpuZoneBegin( ev.gpuZoneBegin, false );
break;
case QueueType::GpuZoneBeginCallstack:
ProcessGpuZoneBeginCallstack( ev.gpuZoneBegin, false );
break;
case QueueType::GpuZoneEnd:
ProcessGpuZoneEnd( ev.gpuZoneEnd, false );
break;
case QueueType::GpuZoneBeginSerial:
ProcessGpuZoneBegin( ev.gpuZoneBegin, true );
break;
case QueueType::GpuZoneBeginCallstackSerial:
ProcessGpuZoneBeginCallstack( ev.gpuZoneBegin, true );
break;
case QueueType::GpuZoneEndSerial:
ProcessGpuZoneEnd( ev.gpuZoneEnd, true );
break;
case QueueType::GpuTime:
ProcessGpuTime( ev.gpuTime );
break;
2018-03-31 19:56:05 +00:00
case QueueType::MemAlloc:
2018-04-01 00:03:34 +00:00
ProcessMemAlloc( ev.memAlloc );
2018-03-31 19:56:05 +00:00
break;
case QueueType::MemFree:
2018-04-01 00:03:34 +00:00
ProcessMemFree( ev.memFree );
2018-03-31 19:56:05 +00:00
break;
2018-06-19 16:52:45 +00:00
case QueueType::MemAllocCallstack:
ProcessMemAllocCallstack( ev.memAlloc );
break;
case QueueType::MemFreeCallstack:
ProcessMemFreeCallstack( ev.memFree );
break;
case QueueType::CallstackMemory:
ProcessCallstackMemory( ev.callstackMemory );
break;
2018-06-21 23:15:49 +00:00
case QueueType::Callstack:
ProcessCallstack( ev.callstack );
break;
case QueueType::CallstackAlloc:
ProcessCallstackAlloc( ev.callstackAlloc );
break;
case QueueType::CallstackFrameSize:
ProcessCallstackFrameSize( ev.callstackFrameSize );
2019-04-01 17:37:39 +00:00
m_serverQuerySpaceLeft++;
break;
2018-06-19 23:07:09 +00:00
case QueueType::CallstackFrame:
ProcessCallstackFrame( ev.callstackFrame );
break;
case QueueType::Terminate:
m_terminate = true;
break;
case QueueType::KeepAlive:
break;
case QueueType::Crash:
m_crashed = true;
break;
2018-08-20 00:07:31 +00:00
case QueueType::CrashReport:
ProcessCrashReport( ev.crashReport );
break;
2019-02-21 21:45:39 +00:00
case QueueType::SysTimeReport:
ProcessSysTime( ev.sysTime );
break;
2019-08-12 22:13:50 +00:00
case QueueType::ContextSwitch:
ProcessContextSwitch( ev.contextSwitch );
break;
2019-08-17 15:05:29 +00:00
case QueueType::ThreadWakeup:
ProcessThreadWakeup( ev.threadWakeup );
break;
2019-08-17 20:32:41 +00:00
case QueueType::TidToPid:
ProcessTidToPid( ev.tidToPid );
break;
case QueueType::ParamSetup:
ProcessParamSetup( ev.paramSetup );
break;
case QueueType::CpuTopology:
ProcessCpuTopology( ev.cpuTopology );
break;
default:
assert( false );
break;
}
2019-01-14 22:08:34 +00:00
2019-01-15 17:55:21 +00:00
return m_failure == Failure::None;
}
void Worker::ProcessThreadContext( const QueueThreadContext& ev )
{
m_refTimeThread = 0;
if( m_threadCtx != ev.thread )
{
m_threadCtx = ev.thread;
m_threadCtxData = RetrieveThread( ev.thread );
}
}
void Worker::ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev )
{
CheckSourceLocation( ev.srcloc );
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeThread + ev.time;
m_refTimeThread = refTime;
const auto start = TscTime( refTime - m_data.baseTime );
zone->SetStart( start );
zone->SetEnd( -1 );
zone->SetSrcLoc( ShrinkSourceLocation( ev.srcloc ) );
zone->SetChild( -1 );
if( m_data.lastTime < start ) m_data.lastTime = start;
NewZone( zone, m_threadCtx );
}
2019-11-10 20:26:57 +00:00
ZoneEvent* Worker::AllocZoneEvent()
{
ZoneEvent* ret;
#ifndef TRACY_NO_STATISTICS
ret = m_slab.Alloc<ZoneEvent>();
#else
2019-11-10 20:26:57 +00:00
if( m_zoneEventPool.empty() )
{
ret = m_slab.Alloc<ZoneEvent>();
}
else
{
ret = m_zoneEventPool.back_and_pop();
}
#endif
2019-11-10 20:26:57 +00:00
memset( &ret->text, 0, sizeof( ZoneEvent::text ) + sizeof( ZoneEvent::callstack ) + sizeof( ZoneEvent::name ) );
return ret;
}
void Worker::ProcessZoneBegin( const QueueZoneBegin& ev )
{
2019-11-10 20:26:57 +00:00
auto zone = AllocZoneEvent();
ProcessZoneBeginImpl( zone, ev );
}
void Worker::ProcessZoneBeginCallstack( const QueueZoneBegin& ev )
{
2019-11-10 20:26:57 +00:00
auto zone = AllocZoneEvent();
ProcessZoneBeginImpl( zone, ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Zone;
next.zone = zone;
}
void Worker::ProcessZoneBeginAllocSrcLocImpl( ZoneEvent* zone, const QueueZoneBegin& ev )
{
auto it = m_pendingSourceLocationPayload.find( ev.srcloc );
assert( it != m_pendingSourceLocationPayload.end() );
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeThread + ev.time;
m_refTimeThread = refTime;
const auto start = TscTime( refTime - m_data.baseTime );
zone->SetStart( start );
zone->SetEnd( -1 );
zone->SetSrcLoc( it->second );
zone->SetChild( -1 );
if( m_data.lastTime < start ) m_data.lastTime = start;
NewZone( zone, m_threadCtx );
m_pendingSourceLocationPayload.erase( it );
}
void Worker::ProcessZoneBeginAllocSrcLoc( const QueueZoneBegin& ev )
{
2019-11-10 20:26:57 +00:00
auto zone = AllocZoneEvent();
ProcessZoneBeginAllocSrcLocImpl( zone, ev );
}
void Worker::ProcessZoneBeginAllocSrcLocCallstack( const QueueZoneBegin& ev )
{
2019-11-10 20:26:57 +00:00
auto zone = AllocZoneEvent();
ProcessZoneBeginAllocSrcLocImpl( zone, ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Zone;
next.zone = zone;
}
2019-01-15 17:55:21 +00:00
void Worker::ProcessZoneEnd( const QueueZoneEnd& ev )
{
auto td = m_threadCtxData;
assert( td );
2019-01-14 22:08:34 +00:00
auto zoneId = td->zoneIdStack.back_and_pop();
2019-01-14 22:22:31 +00:00
if( zoneId != td->nextZoneId )
{
ZoneStackFailure( m_threadCtx, td->stack.back() );
2019-01-15 17:55:21 +00:00
return;
2019-01-14 22:22:31 +00:00
}
2019-01-14 22:08:34 +00:00
td->nextZoneId = 0;
auto& stack = td->stack;
assert( !stack.empty() );
auto zone = stack.back_and_pop();
assert( zone->End() == -1 );
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeThread + ev.time;
m_refTimeThread = refTime;
const auto timeEnd = TscTime( refTime - m_data.baseTime );
zone->SetEnd( timeEnd );
assert( timeEnd >= zone->Start() );
if( m_data.lastTime < timeEnd ) m_data.lastTime = timeEnd;
2019-10-24 22:43:44 +00:00
const auto child = zone->Child();
if( child >= 0 )
{
2019-10-24 22:43:44 +00:00
auto& childVec = m_data.zoneChildren[child];
const auto sz = childVec.size();
if( sz <= 8 * 1024 )
{
2019-11-02 15:17:20 +00:00
Vector<short_ptr<ZoneEvent>> fitVec;
#ifndef TRACY_NO_STATISTICS
fitVec.reserve_exact( sz, m_slab );
memcpy( fitVec.data(), childVec.data(), sz * sizeof( short_ptr<ZoneEvent> ) );
#else
fitVec.set_magic();
auto& fv = *((Vector<ZoneEvent>*)&fitVec);
fv.reserve_exact( sz, m_slab );
auto dst = fv.data();
for( auto& ze : childVec )
{
ZoneEvent* src = ze;
memcpy( dst++, src, sizeof( ZoneEvent ) );
m_zoneEventPool.push_back( src );
}
#endif
2019-03-26 22:02:39 +00:00
fitVec.swap( childVec );
m_data.zoneVectorCache.push_back( std::move( fitVec ) );
}
}
#ifndef TRACY_NO_STATISTICS
assert( !td->childTimeStack.empty() );
const auto timeSpan = timeEnd - zone->Start();
if( timeSpan > 0 )
{
auto slz = GetSourceLocationZones( zone->SrcLoc() );
if( slz->min > timeSpan ) slz->min = timeSpan;
if( slz->max < timeSpan ) slz->max = timeSpan;
slz->total += timeSpan;
slz->sumSq += double( timeSpan ) * timeSpan;
const auto selfSpan = timeSpan - td->childTimeStack.back_and_pop();
if( slz->selfMin > selfSpan ) slz->selfMin = selfSpan;
if( slz->selfMax < selfSpan ) slz->selfMax = selfSpan;
slz->selfTotal += selfSpan;
if( !td->childTimeStack.empty() )
2018-06-05 22:39:22 +00:00
{
td->childTimeStack.back() += timeSpan;
2018-06-05 22:39:22 +00:00
}
}
else
{
td->childTimeStack.pop_back();
}
#endif
}
2019-01-14 22:22:31 +00:00
void Worker::ZoneStackFailure( uint64_t thread, const ZoneEvent* ev )
{
m_failure = Failure::ZoneStack;
m_failureData.thread = thread;
m_failureData.srcloc = ev->SrcLoc();
2019-01-14 22:22:31 +00:00
}
void Worker::ZoneTextFailure( uint64_t thread )
{
m_failure = Failure::ZoneText;
m_failureData.thread = thread;
m_failureData.srcloc = 0;
}
void Worker::ZoneNameFailure( uint64_t thread )
{
m_failure = Failure::ZoneName;
m_failureData.thread = thread;
m_failureData.srcloc = 0;
}
void Worker::MemFreeFailure( uint64_t thread )
{
m_failure = Failure::MemFree;
m_failureData.thread = thread;
m_failureData.srcloc = 0;
}
void Worker::FrameEndFailure()
{
m_failure = Failure::FrameEnd;
m_failureData.thread = 0;
m_failureData.srcloc = 0;
}
void Worker::FrameImageIndexFailure()
{
m_failure = Failure::FrameImageIndex;
m_failureData.thread = 0;
m_failureData.srcloc = 0;
}
void Worker::FrameImageTwiceFailure()
{
m_failure = Failure::FrameImageTwice;
m_failureData.thread = 0;
m_failureData.srcloc = 0;
}
2019-01-14 21:56:10 +00:00
void Worker::ProcessZoneValidation( const QueueZoneValidation& ev )
{
auto td = m_threadCtxData;
if( !td ) td = m_threadCtxData = NoticeThread( m_threadCtx );
2019-01-14 21:56:10 +00:00
td->nextZoneId = ev.id;
}
void Worker::ProcessFrameMark( const QueueFrameMark& ev )
{
2018-08-04 17:47:09 +00:00
auto fd = m_data.frames.Retrieve( ev.name, [this] ( uint64_t name ) {
auto fd = m_slab.AllocInit<FrameData>();
fd->name = name;
2018-08-05 00:09:59 +00:00
fd->continuous = 1;
2018-08-04 17:47:09 +00:00
return fd;
}, [this] ( uint64_t name ) {
2019-04-01 16:52:32 +00:00
Query( ServerQueryFrameName, name );
2018-08-04 17:47:09 +00:00
} );
int32_t frameImage = -1;
auto fis = m_frameImageStaging.find( fd->frames.size() );
if( fis != m_frameImageStaging.end() )
{
frameImage = fis->second;
m_frameImageStaging.erase( fis );
}
2018-08-05 00:09:59 +00:00
assert( fd->continuous == 1 );
2019-08-15 15:52:36 +00:00
const auto time = TscTime( ev.time - m_data.baseTime );
2019-03-21 20:24:07 +00:00
assert( fd->frames.empty() || fd->frames.back().start <= time );
fd->frames.push_back( FrameEvent{ time, -1, frameImage } );
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-09-16 19:31:43 +00:00
#ifndef TRACY_NO_STATISTICS
const auto timeSpan = GetFrameTime( *fd, fd->frames.size() - 1 );
if( timeSpan > 0 )
{
fd->min = std::min( fd->min, timeSpan );
fd->max = std::max( fd->max, timeSpan );
fd->total += timeSpan;
fd->sumSq += double( timeSpan ) * timeSpan;
}
#endif
2018-08-05 00:09:59 +00:00
}
void Worker::ProcessFrameMarkStart( const QueueFrameMark& ev )
{
auto fd = m_data.frames.Retrieve( ev.name, [this] ( uint64_t name ) {
auto fd = m_slab.AllocInit<FrameData>();
fd->name = name;
fd->continuous = 0;
return fd;
}, [this] ( uint64_t name ) {
2019-04-01 16:52:32 +00:00
Query( ServerQueryFrameName, name );
2018-08-05 00:09:59 +00:00
} );
assert( fd->continuous == 0 );
2019-08-15 15:52:36 +00:00
const auto time = TscTime( ev.time - m_data.baseTime );
2019-03-21 20:24:07 +00:00
assert( fd->frames.empty() || ( fd->frames.back().end <= time && fd->frames.back().end != -1 ) );
2019-06-06 19:44:48 +00:00
fd->frames.push_back( FrameEvent{ time, -1, -1 } );
if( m_data.lastTime < time ) m_data.lastTime = time;
2018-08-05 00:09:59 +00:00
}
void Worker::ProcessFrameMarkEnd( const QueueFrameMark& ev )
{
auto fd = m_data.frames.Retrieve( ev.name, [this] ( uint64_t name ) {
auto fd = m_slab.AllocInit<FrameData>();
fd->name = name;
fd->continuous = 0;
return fd;
}, [this] ( uint64_t name ) {
2019-04-01 16:52:32 +00:00
Query( ServerQueryFrameName, name );
2018-08-05 00:09:59 +00:00
} );
assert( fd->continuous == 0 );
2019-08-15 15:52:36 +00:00
const auto time = TscTime( ev.time - m_data.baseTime );
2018-08-05 00:09:59 +00:00
if( fd->frames.empty() )
{
FrameEndFailure();
2018-08-05 00:09:59 +00:00
return;
}
assert( fd->frames.back().end == -1 );
fd->frames.back().end = time;
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-09-16 19:31:43 +00:00
#ifndef TRACY_NO_STATISTICS
const auto timeSpan = GetFrameTime( *fd, fd->frames.size() - 1 );
if( timeSpan > 0 )
{
fd->min = std::min( fd->min, timeSpan );
fd->max = std::max( fd->max, timeSpan );
fd->total += timeSpan;
fd->sumSq += double( timeSpan ) * timeSpan;
}
#endif
}
2019-06-06 19:39:54 +00:00
void Worker::ProcessFrameImage( const QueueFrameImage& ev )
{
auto it = m_pendingFrameImageData.find( ev.image );
assert( it != m_pendingFrameImageData.end() );
auto& frames = m_data.framesBase->frames;
2019-08-26 17:09:12 +00:00
const auto fidx = int64_t( ev.frame ) - int64_t( m_data.frameOffset ) + 1;
if( m_onDemand && fidx <= 1 )
{
m_pendingFrameImageData.erase( it );
return;
}
else if( fidx <= 0 )
{
FrameImageIndexFailure();
return;
}
2019-06-06 19:39:54 +00:00
auto fi = m_slab.Alloc<FrameImage>();
fi->ptr = it->second.image;
fi->csz = it->second.csz;
2019-06-06 19:39:54 +00:00
fi->w = ev.w;
fi->h = ev.h;
2019-08-26 17:09:12 +00:00
fi->frameRef = uint32_t( fidx );
2019-06-12 13:28:32 +00:00
fi->flip = ev.flip;
2019-06-06 19:39:54 +00:00
const auto idx = m_data.frameImage.size();
2019-06-06 20:15:30 +00:00
m_data.frameImage.push_back( fi );
2019-06-06 19:39:54 +00:00
m_pendingFrameImageData.erase( it );
if( fidx >= frames.size() )
{
if( m_frameImageStaging.find( fidx ) != m_frameImageStaging.end() )
{
FrameImageTwiceFailure();
return;
}
m_frameImageStaging.emplace( fidx, idx );
}
else if( frames[fidx].frameImage >= 0 )
{
FrameImageTwiceFailure();
}
else
{
frames[fidx].frameImage = idx;
}
2019-06-06 19:39:54 +00:00
}
void Worker::ProcessZoneText( const QueueZoneText& ev )
{
2019-10-24 20:34:18 +00:00
auto td = RetrieveThread( m_threadCtx );
if( !td || td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )
{
ZoneTextFailure( m_threadCtx );
return;
}
td->nextZoneId = 0;
auto& stack = td->stack;
auto zone = stack.back();
auto it = m_pendingCustomStrings.find( ev.text );
assert( it != m_pendingCustomStrings.end() );
zone->text = StringIdx( it->second.idx );
m_pendingCustomStrings.erase( it );
}
2018-06-29 14:12:17 +00:00
void Worker::ProcessZoneName( const QueueZoneText& ev )
{
2019-10-24 20:34:18 +00:00
auto td = RetrieveThread( m_threadCtx );
if( !td || td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )
{
ZoneNameFailure( m_threadCtx );
return;
}
2018-06-29 14:12:17 +00:00
td->nextZoneId = 0;
2018-06-29 14:12:17 +00:00
auto& stack = td->stack;
auto zone = stack.back();
auto it = m_pendingCustomStrings.find( ev.text );
assert( it != m_pendingCustomStrings.end() );
zone->name = StringIdx( it->second.idx );
m_pendingCustomStrings.erase( it );
}
void Worker::ProcessLockAnnounce( const QueueLockAnnounce& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
auto lm = m_slab.AllocInit<LockMap>();
lm->srcloc = ShrinkSourceLocation( ev.lckloc );
lm->type = ev.type;
2019-08-15 15:52:36 +00:00
lm->timeAnnounce = TscTime( ev.time - m_data.baseTime );
lm->timeTerminate = 0;
lm->valid = true;
2019-05-12 14:17:17 +00:00
lm->isContended = false;
m_data.lockMap.emplace( ev.id, lm );
}
else
{
it->second->srcloc = ShrinkSourceLocation( ev.lckloc );
assert( it->second->type == ev.type );
2019-08-15 15:52:36 +00:00
it->second->timeAnnounce = TscTime( ev.time - m_data.baseTime );
it->second->valid = true;
}
CheckSourceLocation( ev.lckloc );
}
void Worker::ProcessLockTerminate( const QueueLockTerminate& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
auto lm = m_slab.AllocInit<LockMap>();
lm->type = ev.type;
lm->timeAnnounce = 0;
2019-08-15 15:52:36 +00:00
lm->timeTerminate = TscTime( ev.time - m_data.baseTime );
lm->valid = false;
2019-05-12 14:17:17 +00:00
lm->isContended = false;
m_data.lockMap.emplace( ev.id, lm );
}
else
{
assert( it->second->type == ev.type );
2019-08-15 15:52:36 +00:00
it->second->timeTerminate = TscTime( ev.time - m_data.baseTime );
}
}
void Worker::ProcessLockWait( const QueueLockWait& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
auto lm = m_slab.AllocInit<LockMap>();
lm->timeAnnounce = 0;
lm->timeTerminate = 0;
lm->valid = false;
lm->type = ev.type;
2019-05-12 14:17:17 +00:00
lm->isContended = false;
it = m_data.lockMap.emplace( ev.id, lm ).first;
}
auto lev = ev.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::Wait;
InsertLockEvent( *it->second, lev, ev.thread, time );
}
void Worker::ProcessLockObtain( const QueueLockObtain& ev )
{
auto it = m_data.lockMap.find( ev.id );
assert( it != m_data.lockMap.end() );
auto& lock = *it->second;
auto lev = lock.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::Obtain;
InsertLockEvent( lock, lev, ev.thread, time );
}
void Worker::ProcessLockRelease( const QueueLockRelease& ev )
{
auto it = m_data.lockMap.find( ev.id );
assert( it != m_data.lockMap.end() );
auto& lock = *it->second;
auto lev = lock.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::Release;
InsertLockEvent( lock, lev, ev.thread, time );
}
void Worker::ProcessLockSharedWait( const QueueLockWait& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
auto lm = m_slab.AllocInit<LockMap>();
lm->valid = false;
lm->type = ev.type;
2019-05-12 14:17:17 +00:00
lm->isContended = false;
it = m_data.lockMap.emplace( ev.id, lm ).first;
}
assert( ev.type == LockType::SharedLockable );
auto lev = m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::WaitShared;
InsertLockEvent( *it->second, lev, ev.thread, time );
}
void Worker::ProcessLockSharedObtain( const QueueLockObtain& ev )
{
auto it = m_data.lockMap.find( ev.id );
assert( it != m_data.lockMap.end() );
auto& lock = *it->second;
assert( lock.type == LockType::SharedLockable );
auto lev = m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::ObtainShared;
InsertLockEvent( lock, lev, ev.thread, time );
}
void Worker::ProcessLockSharedRelease( const QueueLockRelease& ev )
{
auto it = m_data.lockMap.find( ev.id );
assert( it != m_data.lockMap.end() );
auto& lock = *it->second;
assert( lock.type == LockType::SharedLockable );
auto lev = m_slab.Alloc<LockEventShared>();
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
lev->SetTime( time );
lev->SetSrcLoc( 0 );
lev->type = LockEvent::Type::ReleaseShared;
InsertLockEvent( lock, lev, ev.thread, time );
}
void Worker::ProcessLockMark( const QueueLockMark& ev )
{
CheckSourceLocation( ev.srcloc );
auto lit = m_data.lockMap.find( ev.id );
assert( lit != m_data.lockMap.end() );
auto& lockmap = *lit->second;
auto tid = lockmap.threadMap.find( ev.thread );
assert( tid != lockmap.threadMap.end() );
const auto thread = tid->second;
auto it = lockmap.timeline.end();
for(;;)
{
--it;
if( it->ptr->thread == thread )
{
switch( it->ptr->type )
{
case LockEvent::Type::Obtain:
case LockEvent::Type::ObtainShared:
case LockEvent::Type::Wait:
case LockEvent::Type::WaitShared:
it->ptr->SetSrcLoc( ShrinkSourceLocation( ev.srcloc ) );
return;
default:
break;
}
}
}
}
void Worker::ProcessPlotData( const QueuePlotData& ev )
{
2018-08-04 14:33:03 +00:00
PlotData* plot = m_data.plots.Retrieve( ev.name, [this] ( uint64_t name ) {
auto plot = m_slab.AllocInit<PlotData>();
plot->name = name;
plot->type = PlotType::User;
plot->format = PlotValueFormatting::Number;
2018-08-04 14:33:03 +00:00
return plot;
}, [this]( uint64_t name ) {
2019-04-01 16:52:32 +00:00
Query( ServerQueryPlotName, name );
2018-08-04 14:33:03 +00:00
} );
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeThread + ev.time;
m_refTimeThread = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
switch( ev.type )
{
case PlotDataType::Double:
InsertPlot( plot, time, ev.data.d );
break;
case PlotDataType::Float:
InsertPlot( plot, time, (double)ev.data.f );
break;
case PlotDataType::Int:
InsertPlot( plot, time, (double)ev.data.i );
break;
default:
assert( false );
break;
}
}
void Worker::ProcessPlotConfig( const QueuePlotConfig& ev )
{
2019-11-09 23:00:15 +00:00
PlotData* plot = m_data.plots.Retrieve( ev.name, [this] ( uint64_t name ) {
auto plot = m_slab.AllocInit<PlotData>();
plot->name = name;
plot->type = PlotType::User;
return plot;
}, [this]( uint64_t name ) {
Query( ServerQueryPlotName, name );
} );
plot->format = (PlotValueFormatting)ev.type;
}
void Worker::ProcessMessage( const QueueMessage& ev )
{
auto it = m_pendingCustomStrings.find( ev.text );
assert( it != m_pendingCustomStrings.end() );
auto msg = m_slab.Alloc<MessageData>();
const auto time = TscTime( ev.time - m_data.baseTime );
msg->time = time;
msg->ref = StringRef( StringRef::Type::Idx, it->second.idx );
2019-08-28 19:03:01 +00:00
msg->thread = CompressThread( m_threadCtx );
2019-05-10 18:21:35 +00:00
msg->color = 0xFFFFFFFF;
2019-11-14 23:42:44 +00:00
msg->callstack.SetVal( 0 );
if( m_data.lastTime < time ) m_data.lastTime = time;
InsertMessageData( msg );
m_pendingCustomStrings.erase( it );
}
void Worker::ProcessMessageLiteral( const QueueMessage& ev )
{
CheckString( ev.text );
auto msg = m_slab.Alloc<MessageData>();
const auto time = TscTime( ev.time - m_data.baseTime );
msg->time = time;
msg->ref = StringRef( StringRef::Type::Ptr, ev.text );
2019-08-28 19:03:01 +00:00
msg->thread = CompressThread( m_threadCtx );
2019-05-10 18:21:35 +00:00
msg->color = 0xFFFFFFFF;
2019-11-14 23:42:44 +00:00
msg->callstack.SetVal( 0 );
if( m_data.lastTime < time ) m_data.lastTime = time;
InsertMessageData( msg );
}
2019-05-10 18:17:44 +00:00
void Worker::ProcessMessageColor( const QueueMessageColor& ev )
{
auto it = m_pendingCustomStrings.find( ev.text );
assert( it != m_pendingCustomStrings.end() );
auto msg = m_slab.Alloc<MessageData>();
const auto time = TscTime( ev.time - m_data.baseTime );
msg->time = time;
2019-05-10 18:17:44 +00:00
msg->ref = StringRef( StringRef::Type::Idx, it->second.idx );
2019-08-28 19:03:01 +00:00
msg->thread = CompressThread( m_threadCtx );
2019-05-10 18:21:35 +00:00
msg->color = 0xFF000000 | ( ev.r << 16 ) | ( ev.g << 8 ) | ev.b;
2019-11-14 23:42:44 +00:00
msg->callstack.SetVal( 0 );
if( m_data.lastTime < time ) m_data.lastTime = time;
InsertMessageData( msg );
2019-05-10 18:17:44 +00:00
m_pendingCustomStrings.erase( it );
}
void Worker::ProcessMessageLiteralColor( const QueueMessageColor& ev )
{
CheckString( ev.text );
auto msg = m_slab.Alloc<MessageData>();
const auto time = TscTime( ev.time - m_data.baseTime );
msg->time = time;
2019-05-10 18:17:44 +00:00
msg->ref = StringRef( StringRef::Type::Ptr, ev.text );
2019-08-28 19:03:01 +00:00
msg->thread = CompressThread( m_threadCtx );
2019-05-10 18:21:35 +00:00
msg->color = 0xFF000000 | ( ev.r << 16 ) | ( ev.g << 8 ) | ev.b;
2019-11-14 23:42:44 +00:00
msg->callstack.SetVal( 0 );
if( m_data.lastTime < time ) m_data.lastTime = time;
InsertMessageData( msg );
2019-05-10 18:17:44 +00:00
}
2019-11-14 23:42:44 +00:00
void Worker::ProcessMessageCallstack( const QueueMessage& ev )
{
ProcessMessage( ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Message;
}
void Worker::ProcessMessageLiteralCallstack( const QueueMessage& ev )
{
ProcessMessageLiteral( ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Message;
}
void Worker::ProcessMessageColorCallstack( const QueueMessageColor& ev )
{
ProcessMessageColor( ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Message;
}
void Worker::ProcessMessageLiteralColorCallstack( const QueueMessageColor& ev )
{
ProcessMessageLiteralColor( ev );
auto& next = m_nextCallstack[m_threadCtx];
next.type = NextCallstackType::Message;
}
2019-07-12 16:30:45 +00:00
void Worker::ProcessMessageAppInfo( const QueueMessage& ev )
{
auto it = m_pendingCustomStrings.find( ev.text );
assert( it != m_pendingCustomStrings.end() );
m_data.appInfo.push_back( StringRef( StringRef::Type::Idx, it->second.idx ) );
const auto time = TscTime( ev.time - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-07-12 16:30:45 +00:00
m_pendingCustomStrings.erase( it );
}
void Worker::ProcessGpuNewContext( const QueueGpuNewContext& ev )
{
assert( !m_gpuCtxMap[ev.context] );
int64_t gpuTime;
if( ev.period == 1.f )
{
gpuTime = ev.gpuTime;
}
else
{
gpuTime = int64_t( double( ev.period ) * ev.gpuTime ); // precision loss
}
auto gpu = m_slab.AllocInit<GpuCtxData>();
memset( gpu->query, 0, sizeof( gpu->query ) );
2019-08-15 15:52:36 +00:00
gpu->timeDiff = TscTime( ev.cpuTime - m_data.baseTime ) - gpuTime;
gpu->thread = ev.thread;
gpu->accuracyBits = ev.accuracyBits;
gpu->period = ev.period;
gpu->count = 0;
m_data.gpuData.push_back( gpu );
m_gpuCtxMap[ev.context] = gpu;
}
void Worker::ProcessGpuZoneBeginImpl( GpuEvent* zone, const QueueGpuZoneBegin& ev, bool serial )
{
2019-10-13 12:13:04 +00:00
m_data.gpuCnt++;
auto ctx = m_gpuCtxMap[ev.context];
assert( ctx );
CheckSourceLocation( ev.srcloc );
int64_t cpuTime;
if( serial )
{
2019-10-24 20:24:00 +00:00
cpuTime = m_refTimeSerial + ev.cpuTime;
m_refTimeSerial = cpuTime;
}
else
{
2019-10-24 20:24:00 +00:00
cpuTime = m_refTimeThread + ev.cpuTime;
m_refTimeThread = cpuTime;
}
const auto time = TscTime( cpuTime - m_data.baseTime );
zone->SetCpuStart( time );
zone->SetCpuEnd( -1 );
zone->SetGpuStart( -1 );
zone->SetGpuEnd( -1 );
zone->SetSrcLoc( ShrinkSourceLocation( ev.srcloc ) );
zone->callstack.SetVal( 0 );
zone->SetChild( -1 );
2019-09-23 15:27:49 +00:00
uint64_t ztid;
if( ctx->thread == 0 )
{
// Vulkan context is not bound to any single thread.
zone->SetThread( CompressThread( ev.thread ) );
2019-09-23 15:27:49 +00:00
ztid = ev.thread;
}
else
{
// OpenGL doesn't need per-zone thread id. It still can be sent,
// because it may be needed for callstack collection purposes.
zone->SetThread( 0 );
2019-09-23 15:27:49 +00:00
ztid = 0;
}
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-09-23 15:27:49 +00:00
auto td = ctx->threadData.find( ztid );
if( td == ctx->threadData.end() )
{
td = ctx->threadData.emplace( ztid, GpuCtxThreadData {} ).first;
}
auto timeline = &td->second.timeline;
auto& stack = td->second.stack;
if( !stack.empty() )
{
2019-09-23 15:27:49 +00:00
auto back = stack.back();
if( back->Child() < 0 )
{
back->SetChild( int32_t( m_data.gpuChildren.size() ) );
2019-11-02 14:52:34 +00:00
m_data.gpuChildren.push_back( Vector<short_ptr<GpuEvent>>() );
}
timeline = &m_data.gpuChildren[back->Child()];
}
timeline->push_back( zone );
2019-09-23 15:27:49 +00:00
stack.push_back( zone );
assert( !ctx->query[ev.queryId] );
ctx->query[ev.queryId] = zone;
}
void Worker::ProcessGpuZoneBegin( const QueueGpuZoneBegin& ev, bool serial )
{
2019-02-15 00:31:58 +00:00
auto zone = m_slab.Alloc<GpuEvent>();
ProcessGpuZoneBeginImpl( zone, ev, serial );
}
void Worker::ProcessGpuZoneBeginCallstack( const QueueGpuZoneBegin& ev, bool serial )
{
2019-02-15 00:31:58 +00:00
auto zone = m_slab.Alloc<GpuEvent>();
ProcessGpuZoneBeginImpl( zone, ev, serial );
auto& next = m_nextCallstack[ev.thread];
next.type = NextCallstackType::Gpu;
next.gpu = zone;
}
void Worker::ProcessGpuZoneEnd( const QueueGpuZoneEnd& ev, bool serial )
{
auto ctx = m_gpuCtxMap[ev.context];
assert( ctx );
2019-09-23 15:27:49 +00:00
auto td = ctx->threadData.find( ev.thread );
assert( td != ctx->threadData.end() );
assert( !td->second.stack.empty() );
auto zone = td->second.stack.back_and_pop();
assert( !ctx->query[ev.queryId] );
ctx->query[ev.queryId] = zone;
int64_t cpuTime;
if( serial )
{
2019-10-24 20:24:00 +00:00
cpuTime = m_refTimeSerial + ev.cpuTime;
m_refTimeSerial = cpuTime;
}
else
{
2019-10-24 20:24:00 +00:00
cpuTime = m_refTimeThread + ev.cpuTime;
m_refTimeThread = cpuTime;
}
const auto time = TscTime( cpuTime - m_data.baseTime );
zone->SetCpuEnd( time );
if( m_data.lastTime < time ) m_data.lastTime = time;
}
void Worker::ProcessGpuTime( const QueueGpuTime& ev )
{
auto ctx = m_gpuCtxMap[ev.context];
assert( ctx );
const int64_t tref = m_refTimeGpu + ev.gpuTime;
m_refTimeGpu = tref;
const int64_t t = std::max<int64_t>( 0, tref );
2019-10-25 17:52:01 +00:00
int64_t gpuTime;
if( ctx->period == 1.f )
{
2019-10-25 17:52:01 +00:00
gpuTime = t;
}
else
{
2019-10-25 17:52:01 +00:00
gpuTime = int64_t( double( ctx->period ) * t ); // precision loss
}
auto zone = ctx->query[ev.queryId];
assert( zone );
ctx->query[ev.queryId] = nullptr;
if( zone->GpuStart() < 0 )
{
const auto time = ctx->timeDiff + gpuTime;
zone->SetGpuStart( time );
if( m_data.lastTime < time ) m_data.lastTime = time;
ctx->count++;
}
else
{
auto time = ctx->timeDiff + gpuTime;
if( time < zone->GpuStart() )
{
auto tmp = zone->GpuStart();
std::swap( time, tmp );
zone->SetGpuStart( tmp );
}
zone->SetGpuEnd( time );
if( m_data.lastTime < time ) m_data.lastTime = time;
}
}
2018-04-01 00:03:34 +00:00
void Worker::ProcessMemAlloc( const QueueMemAlloc& ev )
{
2019-10-24 20:24:00 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2018-08-27 23:48:19 +00:00
NoticeThread( ev.thread );
2018-04-01 00:03:34 +00:00
assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() );
assert( m_data.memory.data.empty() || m_data.memory.data.back().TimeAlloc() <= time );
2018-04-01 00:03:34 +00:00
m_data.memory.active.emplace( ev.ptr, m_data.memory.data.size() );
2018-04-01 00:03:34 +00:00
2018-04-10 14:06:01 +00:00
const auto ptr = ev.ptr;
uint32_t lo;
uint16_t hi;
memcpy( &lo, ev.size, 4 );
memcpy( &hi, ev.size+4, 2 );
const uint64_t size = lo | ( uint64_t( hi ) << 32 );
auto& mem = m_data.memory.data.push_next();
mem.SetPtr( ptr );
mem.SetSize( size );
mem.SetTimeAlloc( time );
mem.SetThreadAlloc( CompressThread( ev.thread ) );
mem.SetTimeFree( -1 );
mem.SetThreadFree( 0 );
mem.SetCsAlloc( 0 );
mem.csFree.SetVal( 0 );
2018-04-01 00:03:34 +00:00
2018-04-10 14:06:01 +00:00
const auto low = m_data.memory.low;
const auto high = m_data.memory.high;
const auto ptrend = ptr + size;
m_data.memory.low = std::min( low, ptr );
m_data.memory.high = std::max( high, ptrend );
m_data.memory.usage += size;
MemAllocChanged( time );
2018-04-01 00:03:34 +00:00
}
bool Worker::ProcessMemFree( const QueueMemFree& ev )
2018-04-01 00:03:34 +00:00
{
2019-11-07 15:14:23 +00:00
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
2018-12-20 16:03:09 +00:00
if( ev.ptr == 0 ) return false;
2018-04-01 00:03:34 +00:00
auto it = m_data.memory.active.find( ev.ptr );
if( it == m_data.memory.active.end() )
{
if( !m_ignoreMemFreeFaults )
{
MemFreeFailure( ev.thread );
}
return false;
}
2019-10-24 20:24:00 +00:00
const auto time = TscTime( refTime - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2018-08-27 23:48:19 +00:00
NoticeThread( ev.thread );
2018-05-02 15:59:50 +00:00
m_data.memory.frees.push_back( it->second );
auto& mem = m_data.memory.data[it->second];
mem.SetTimeFree( time );
mem.SetThreadFree( CompressThread( ev.thread ) );
m_data.memory.usage -= mem.Size();
2018-04-01 18:13:01 +00:00
m_data.memory.active.erase( it );
MemAllocChanged( time );
return true;
}
2018-06-19 16:52:45 +00:00
void Worker::ProcessMemAllocCallstack( const QueueMemAlloc& ev )
{
m_lastMemActionCallstack = m_data.memory.data.size();
ProcessMemAlloc( ev );
m_lastMemActionWasAlloc = true;
2018-06-19 16:52:45 +00:00
}
void Worker::ProcessMemFreeCallstack( const QueueMemFree& ev )
{
if( ProcessMemFree( ev ) )
{
m_lastMemActionCallstack = m_data.memory.frees.back();
m_lastMemActionWasAlloc = false;
}
else
{
m_lastMemActionCallstack = std::numeric_limits<uint64_t>::max();
}
2018-06-19 16:52:45 +00:00
}
void Worker::ProcessCallstackMemory( const QueueCallstackMemory& ev )
{
assert( m_pendingCallstackPtr == ev.ptr );
m_pendingCallstackPtr = 0;
2018-06-19 19:34:36 +00:00
if( m_lastMemActionCallstack != std::numeric_limits<uint64_t>::max() )
{
auto& mem = m_data.memory.data[m_lastMemActionCallstack];
if( m_lastMemActionWasAlloc )
{
mem.SetCsAlloc( m_pendingCallstackId );
}
else
{
mem.csFree.SetVal( m_pendingCallstackId );
}
}
2018-06-19 16:52:45 +00:00
}
2018-06-21 23:15:49 +00:00
void Worker::ProcessCallstack( const QueueCallstack& ev )
{
assert( m_pendingCallstackPtr == ev.ptr );
m_pendingCallstackPtr = 0;
2018-06-21 23:15:49 +00:00
auto nit = m_nextCallstack.find( m_threadCtx );
2018-06-21 23:15:49 +00:00
assert( nit != m_nextCallstack.end() );
auto& next = nit->second;
switch( next.type )
{
case NextCallstackType::Zone:
next.zone->callstack.SetVal( m_pendingCallstackId );
2018-06-21 23:15:49 +00:00
break;
case NextCallstackType::Gpu:
next.gpu->callstack.SetVal( m_pendingCallstackId );
break;
2018-08-20 00:07:31 +00:00
case NextCallstackType::Crash:
2019-03-26 20:41:44 +00:00
m_data.crashEvent.callstack = m_pendingCallstackId;
2018-08-20 00:07:31 +00:00
break;
2019-11-14 23:42:44 +00:00
case NextCallstackType::Message:
{
auto td = m_threadCtxData;
if( !td ) td = m_threadCtxData = RetrieveThread( m_threadCtx );
assert( td );
td->messages.back()->callstack.SetVal( m_pendingCallstackId );
break;
}
2018-06-21 23:15:49 +00:00
default:
assert( false );
break;
}
}
void Worker::ProcessCallstackAlloc( const QueueCallstackAlloc& ev )
{
assert( m_pendingCallstackPtr == ev.ptr );
m_pendingCallstackPtr = 0;
auto nit = m_nextCallstack.find( m_threadCtx );
assert( nit != m_nextCallstack.end() );
auto& next = nit->second;
switch( next.type )
{
case NextCallstackType::Zone:
next.zone->callstack.SetVal( m_pendingCallstackId );
break;
case NextCallstackType::Gpu:
next.gpu->callstack.SetVal( m_pendingCallstackId );
break;
case NextCallstackType::Crash:
2019-03-26 20:41:44 +00:00
m_data.crashEvent.callstack = m_pendingCallstackId;
break;
2019-11-14 23:42:44 +00:00
case NextCallstackType::Message:
{
auto td = m_threadCtxData;
if( !td ) td = m_threadCtxData = RetrieveThread( m_threadCtx );
assert( td );
td->messages.back()->callstack.SetVal( m_pendingCallstackId );
break;
}
default:
assert( false );
break;
}
}
void Worker::ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev )
2018-06-19 23:07:09 +00:00
{
assert( !m_callstackFrameStaging );
assert( m_pendingCallstackSubframes == 0 );
2018-06-20 21:42:00 +00:00
assert( m_pendingCallstackFrames > 0 );
m_pendingCallstackFrames--;
m_pendingCallstackSubframes = ev.size;
// Frames may be duplicated due to recursion
auto fmit = m_data.callstackFrameMap.find( PackPointer( ev.ptr ) );
if( fmit == m_data.callstackFrameMap.end() )
{
m_callstackFrameStaging = m_slab.Alloc<CallstackFrameData>();
m_callstackFrameStaging->size = ev.size;
m_callstackFrameStaging->data = m_slab.Alloc<CallstackFrame>( ev.size );
m_callstackFrameStagingPtr = ev.ptr;
}
}
void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev )
{
assert( m_pendingCallstackSubframes > 0 );
auto nit = m_pendingCustomStrings.find( ev.name );
assert( nit != m_pendingCustomStrings.end() );
auto fit = m_pendingCustomStrings.find( ev.file );
assert( fit != m_pendingCustomStrings.end() );
2018-06-19 23:07:09 +00:00
if( m_callstackFrameStaging )
2018-06-19 23:07:09 +00:00
{
const auto idx = m_callstackFrameStaging->size - m_pendingCallstackSubframes;
2018-06-19 23:07:09 +00:00
m_callstackFrameStaging->data[idx].name = StringIdx( nit->second.idx );
m_callstackFrameStaging->data[idx].file = StringIdx( fit->second.idx );
m_callstackFrameStaging->data[idx].line = ev.line;
2018-06-19 23:07:09 +00:00
if( --m_pendingCallstackSubframes == 0 )
{
assert( m_data.callstackFrameMap.find( PackPointer( m_callstackFrameStagingPtr ) ) == m_data.callstackFrameMap.end() );
m_data.callstackFrameMap.emplace( PackPointer( m_callstackFrameStagingPtr ), m_callstackFrameStaging );
m_callstackFrameStaging = nullptr;
}
}
else
{
m_pendingCallstackSubframes--;
2018-06-19 23:07:09 +00:00
}
m_pendingCustomStrings.erase( nit );
m_pendingCustomStrings.erase( m_pendingCustomStrings.find( ev.file ) );
2018-06-19 23:07:09 +00:00
}
2018-08-20 00:07:31 +00:00
void Worker::ProcessCrashReport( const QueueCrashReport& ev )
{
CheckString( ev.text );
auto& next = m_nextCallstack[m_threadCtx];
2018-08-20 00:07:31 +00:00
next.type = NextCallstackType::Crash;
m_data.crashEvent.thread = m_threadCtx;
2019-08-15 15:52:36 +00:00
m_data.crashEvent.time = TscTime( ev.time - m_data.baseTime );
2019-03-26 20:41:44 +00:00
m_data.crashEvent.message = ev.text;
m_data.crashEvent.callstack = 0;
2018-08-20 00:07:31 +00:00
}
2019-02-21 21:45:39 +00:00
void Worker::ProcessSysTime( const QueueSysTime& ev )
{
2019-08-15 15:52:36 +00:00
const auto time = TscTime( ev.time - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-02-21 21:45:39 +00:00
const auto val = ev.sysTime;
if( !m_sysTimePlot )
{
m_sysTimePlot = m_slab.AllocInit<PlotData>();
m_sysTimePlot->name = 0;
m_sysTimePlot->type = PlotType::SysTime;
m_sysTimePlot->format = PlotValueFormatting::Percentage;
2019-02-21 21:45:39 +00:00
m_sysTimePlot->min = val;
m_sysTimePlot->max = val;
m_sysTimePlot->data.push_back( { time, val } );
m_data.plots.Data().push_back( m_sysTimePlot );
}
else
{
assert( !m_sysTimePlot->data.empty() );
assert( m_sysTimePlot->data.back().time.Val() <= time );
2019-02-21 21:45:39 +00:00
if( m_sysTimePlot->min > val ) m_sysTimePlot->min = val;
else if( m_sysTimePlot->max < val ) m_sysTimePlot->max = val;
m_sysTimePlot->data.push_back_non_empty( { time, val } );
}
}
2019-08-12 22:13:50 +00:00
void Worker::ProcessContextSwitch( const QueueContextSwitch& ev )
{
2019-10-25 17:13:11 +00:00
const auto refTime = m_refTimeCtx + ev.time;
m_refTimeCtx = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-08-12 22:13:50 +00:00
if( ev.cpu >= m_data.cpuDataCount ) m_data.cpuDataCount = ev.cpu + 1;
2019-08-16 14:28:58 +00:00
auto& cs = m_data.cpuData[ev.cpu].cs;
2019-08-12 22:13:50 +00:00
if( ev.oldThread != 0 )
{
auto it = m_data.ctxSwitch.find( ev.oldThread );
if( it != m_data.ctxSwitch.end() )
{
auto& data = it->second->v;
assert( !data.empty() );
auto& item = data.back();
assert( item.Start() <= time );
assert( item.End() == -1 );
item.SetEnd( time );
item.SetReason( ev.reason );
item.SetState( ev.state );
2019-08-17 23:50:49 +00:00
const auto dt = time - item.Start();
it->second->runningTime += dt;
auto tdit = m_data.cpuThreadData.find( ev.oldThread );
if( tdit == m_data.cpuThreadData.end() )
{
tdit = m_data.cpuThreadData.emplace( ev.oldThread, CpuThreadData {} ).first;
}
tdit->second.runningRegions++;
tdit->second.runningTime += dt;
2019-08-12 22:13:50 +00:00
}
2019-08-16 14:28:58 +00:00
if( !cs.empty() )
{
auto& cx = cs.back();
assert( m_data.externalThreadCompress.DecompressThread( cx.Thread() ) == ev.oldThread );
2019-08-16 14:28:58 +00:00
cx.SetEnd( time );
}
2019-08-12 22:13:50 +00:00
}
if( ev.newThread != 0 )
{
auto it = m_data.ctxSwitch.find( ev.newThread );
if( it == m_data.ctxSwitch.end() )
{
auto ctx = m_slab.AllocInit<ContextSwitch>();
it = m_data.ctxSwitch.emplace( ev.newThread, ctx ).first;
}
auto& data = it->second->v;
2019-08-17 15:05:29 +00:00
ContextSwitchData* item = nullptr;
2019-08-17 23:50:49 +00:00
bool migration = false;
2019-08-17 15:05:29 +00:00
if( !data.empty() && data.back().Reason() == ContextSwitchData::Wakeup )
{
item = &data.back();
2019-08-17 23:50:49 +00:00
if( data.size() > 1 )
{
migration = data[data.size()-2].Cpu() != ev.cpu;
}
2019-08-17 15:05:29 +00:00
}
else
{
2019-11-02 15:21:46 +00:00
assert( data.empty() || (uint64_t)data.back().End() <= (uint64_t)time );
2019-08-17 23:50:49 +00:00
if( !data.empty() )
{
migration = data.back().Cpu() != ev.cpu;
}
2019-08-17 15:05:29 +00:00
item = &data.push_next();
item->SetWakeup( time );
2019-08-17 15:05:29 +00:00
}
item->SetStart( time );
item->SetEnd( -1 );
item->SetCpu( ev.cpu );
item->SetReason( -1 );
item->SetState( -1 );
2019-08-16 14:28:58 +00:00
auto& cx = cs.push_next();
cx.SetStart( time );
2019-08-16 19:20:04 +00:00
cx.SetEnd( -1 );
cx.SetThread( m_data.externalThreadCompress.CompressThread( ev.newThread ) );
CheckExternalName( ev.newThread );
2019-08-17 23:50:49 +00:00
if( migration )
{
auto tdit = m_data.cpuThreadData.find( ev.newThread );
if( tdit == m_data.cpuThreadData.end() )
{
tdit = m_data.cpuThreadData.emplace( ev.newThread, CpuThreadData {} ).first;
}
tdit->second.migrations++;
}
2019-08-12 22:13:50 +00:00
}
}
2019-08-17 15:05:29 +00:00
void Worker::ProcessThreadWakeup( const QueueThreadWakeup& ev )
{
2019-10-25 17:13:11 +00:00
const auto refTime = m_refTimeCtx + ev.time;
m_refTimeCtx = refTime;
const auto time = TscTime( refTime - m_data.baseTime );
if( m_data.lastTime < time ) m_data.lastTime = time;
2019-08-17 15:05:29 +00:00
auto it = m_data.ctxSwitch.find( ev.thread );
if( it == m_data.ctxSwitch.end() )
{
auto ctx = m_slab.AllocInit<ContextSwitch>();
it = m_data.ctxSwitch.emplace( ev.thread, ctx ).first;
}
auto& data = it->second->v;
if( !data.empty() && data.back().End() < 0 ) return; // wakeup of a running thread
auto& item = data.push_next();
item.SetWakeup( time );
2019-08-17 15:05:29 +00:00
item.SetStart( time );
item.SetEnd( -1 );
item.SetCpu( 0 );
item.SetReason( ContextSwitchData::Wakeup );
item.SetState( -1 );
}
2019-08-17 20:32:41 +00:00
void Worker::ProcessTidToPid( const QueueTidToPid& ev )
{
assert( m_data.tidToPid.find( ev.tid ) == m_data.tidToPid.end() );
m_data.tidToPid.emplace( ev.tid, ev.pid );
}
void Worker::ProcessParamSetup( const QueueParamSetup& ev )
{
CheckString( ev.name );
m_params.push_back( Parameter { ev.idx, StringRef( StringRef::Ptr, ev.name ), bool( ev.isBool ), ev.val } );
}
void Worker::ProcessCpuTopology( const QueueCpuTopology& ev )
{
auto package = m_data.cpuTopology.find( ev.package );
if( package == m_data.cpuTopology.end() ) package = m_data.cpuTopology.emplace( ev.package, flat_hash_map<uint32_t, std::vector<uint32_t>> {} ).first;
auto core = package->second.find( ev.core );
if( core == package->second.end() ) core = package->second.emplace( ev.core, std::vector<uint32_t> {} ).first;
core->second.emplace_back( ev.thread );
2019-11-29 21:46:57 +00:00
assert( m_data.cpuTopologyMap.find( ev.thread ) == m_data.cpuTopologyMap.end() );
m_data.cpuTopologyMap.emplace( ev.thread, CpuThreadTopology { ev.package, ev.core } );
}
void Worker::MemAllocChanged( int64_t time )
{
const auto val = (double)m_data.memory.usage;
if( !m_data.memory.plot )
{
CreateMemAllocPlot();
m_data.memory.plot->min = val;
m_data.memory.plot->max = val;
m_data.memory.plot->data.push_back( { time, val } );
}
else
{
assert( !m_data.memory.plot->data.empty() );
assert( m_data.memory.plot->data.back().time.Val() <= time );
if( m_data.memory.plot->min > val ) m_data.memory.plot->min = val;
else if( m_data.memory.plot->max < val ) m_data.memory.plot->max = val;
m_data.memory.plot->data.push_back_non_empty( { time, val } );
}
}
void Worker::CreateMemAllocPlot()
{
assert( !m_data.memory.plot );
m_data.memory.plot = m_slab.AllocInit<PlotData>();
m_data.memory.plot->name = 0;
m_data.memory.plot->type = PlotType::Memory;
m_data.memory.plot->format = PlotValueFormatting::Memory;
2018-08-04 17:47:09 +00:00
m_data.memory.plot->data.push_back( { GetFrameBegin( *m_data.framesBase, 0 ), 0. } );
2018-08-04 14:33:03 +00:00
m_data.plots.Data().push_back( m_data.memory.plot );
2018-04-01 00:03:34 +00:00
}
void Worker::ReconstructMemAllocPlot()
{
2018-05-02 15:59:50 +00:00
auto& mem = m_data.memory;
#ifdef MY_LIBCPP_SUCKS
pdqsort_branchless( mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );
#else
std::sort( std::execution::par_unseq, mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );
#endif
2018-05-02 15:59:50 +00:00
const auto psz = mem.data.size() + mem.frees.size() + 1;
PlotData* plot;
{
std::lock_guard<std::shared_mutex> lock( m_data.lock );
plot = m_slab.AllocInit<PlotData>();
}
plot->name = 0;
plot->type = PlotType::Memory;
plot->format = PlotValueFormatting::Memory;
plot->data.reserve_exact( psz, m_slab );
2018-05-02 15:59:50 +00:00
auto aptr = mem.data.begin();
auto aend = mem.data.end();
auto fptr = mem.frees.begin();
auto fend = mem.frees.end();
double max = 0;
double usage = 0;
auto ptr = plot->data.data();
2018-08-04 17:47:09 +00:00
ptr->time = GetFrameBegin( *m_data.framesBase, 0 );
ptr->val = 0;
ptr++;
2018-04-30 11:44:44 +00:00
if( aptr != aend && fptr != fend )
{
auto atime = aptr->TimeAlloc();
auto ftime = mem.data[*fptr].TimeFree();
2018-04-30 11:44:44 +00:00
for(;;)
{
2018-04-30 11:44:44 +00:00
if( atime < ftime )
{
usage += int64_t( aptr->Size() );
2018-04-30 11:44:44 +00:00
assert( usage >= 0 );
if( max < usage ) max = usage;
ptr->time = atime;
ptr->val = usage;
ptr++;
aptr++;
if( aptr == aend ) break;
atime = aptr->TimeAlloc();
2018-04-30 11:44:44 +00:00
}
else
{
usage -= int64_t( mem.data[*fptr].Size() );
2018-04-30 11:44:44 +00:00
assert( usage >= 0 );
if( max < usage ) max = usage;
ptr->time = ftime;
ptr->val = usage;
ptr++;
fptr++;
if( fptr == fend ) break;
ftime = mem.data[*fptr].TimeFree();
2018-04-30 11:44:44 +00:00
}
}
}
2018-04-30 11:44:44 +00:00
while( aptr != aend )
{
assert( aptr->TimeFree() < 0 );
int64_t time = aptr->TimeAlloc();
usage += int64_t( aptr->Size() );
assert( usage >= 0 );
if( max < usage ) max = usage;
ptr->time = time;
ptr->val = usage;
ptr++;
aptr++;
}
while( fptr != fend )
{
2019-01-29 21:10:14 +00:00
const auto& memData = mem.data[*fptr];
int64_t time = memData.TimeFree();
usage -= int64_t( memData.Size() );
assert( usage >= 0 );
assert( max >= usage );
ptr->time = time;
ptr->val = usage;
ptr++;
fptr++;
}
plot->min = 0;
plot->max = max;
std::lock_guard<std::shared_mutex> lock( m_data.lock );
2018-08-04 14:33:03 +00:00
m_data.plots.Data().insert( m_data.plots.Data().begin(), plot );
m_data.memory.plot = plot;
}
#ifndef TRACY_NO_STATISTICS
void Worker::ReconstructContextSwitchUsage()
{
assert( m_data.cpuDataCount != 0 );
const auto cpucnt = m_data.cpuDataCount;
auto& vec = m_data.ctxUsage;
vec.push_back( ContextSwitchUsage( 0, 0, 0 ) );
struct Cpu
{
bool startDone;
Vector<ContextSwitchCpu>::iterator it;
Vector<ContextSwitchCpu>::iterator end;
};
std::vector<Cpu> cpus;
cpus.reserve( cpucnt );
for( int i=0; i<cpucnt; i++ )
{
cpus.emplace_back( Cpu { false, m_data.cpuData[i].cs.begin(), m_data.cpuData[i].cs.end() } );
}
uint8_t other = 0;
uint8_t own = 0;
for(;;)
{
int64_t nextTime = std::numeric_limits<int64_t>::max();
bool atEnd = true;
for( int i=0; i<cpucnt; i++ )
{
if( cpus[i].it != cpus[i].end )
{
atEnd = false;
const auto ct = !cpus[i].startDone ? cpus[i].it->Start() : cpus[i].it->End();
if( ct < nextTime ) nextTime = ct;
}
}
if( atEnd ) break;
for( int i=0; i<cpucnt; i++ )
{
while( cpus[i].it != cpus[i].end )
{
const auto ct = !cpus[i].startDone ? cpus[i].it->Start() : cpus[i].it->End();
if( nextTime != ct ) break;
const auto isOwn = GetPidFromTid( DecompressThreadExternal( cpus[i].it->Thread() ) ) == m_pid;
if( !cpus[i].startDone )
{
if( isOwn )
{
own++;
assert( own <= cpucnt );
}
else
{
other++;
assert( other <= cpucnt );
}
if( cpus[i].it->End() < 0 )
{
cpus[i].it++;
assert( cpus[i].it = cpus[i].end );
}
else
{
cpus[i].startDone = true;
}
}
else
{
if( isOwn )
{
assert( own > 0 );
own--;
}
else
{
assert( other > 0 );
other--;
}
cpus[i].startDone = false;
cpus[i].it++;
}
}
}
const auto& back = vec.back();
if( back.Other() != other || back.Own() != own )
{
vec.push_back( ContextSwitchUsage( nextTime, other, own ) );
}
}
std::lock_guard<std::shared_mutex> lock( m_data.lock );
m_data.ctxUsageReady = true;
}
#endif
void Worker::ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t& refTime, int32_t& childIdx )
{
uint64_t sz;
2018-04-30 23:47:56 +00:00
f.Read( sz );
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
if( sz == 0 )
{
zone->SetChild( -1 );
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
}
else
{
const auto idx = childIdx;
childIdx++;
zone->SetChild( idx );
ReadTimeline( f, m_data.zoneChildren[idx], sz, refTime, childIdx );
}
}
void Worker::ReadTimelinePre0510( FileRead& f, ZoneEvent* zone, int64_t& refTime, int fileVer )
2019-08-12 17:18:17 +00:00
{
uint64_t sz;
f.Read( sz );
if( sz == 0 )
{
zone->SetChild( -1 );
2019-08-12 17:18:17 +00:00
}
else
{
2019-10-30 22:55:21 +00:00
const auto child = m_data.zoneChildren.size();
zone->SetChild( child );
2019-11-02 15:17:20 +00:00
m_data.zoneChildren.push_back( Vector<short_ptr<ZoneEvent>>() );
Vector<short_ptr<ZoneEvent>> tmp;
ReadTimelinePre0510( f, tmp, sz, refTime, fileVer );
2019-10-30 22:55:21 +00:00
m_data.zoneChildren[child] = std::move( tmp );
2019-08-12 17:18:17 +00:00
}
}
void Worker::ReadTimeline( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx )
{
uint64_t sz;
2018-04-30 23:47:56 +00:00
f.Read( sz );
if( sz == 0 )
{
zone->SetChild( -1 );
}
else
{
const auto idx = childIdx;
childIdx++;
zone->SetChild( idx );
ReadTimeline( f, m_data.gpuChildren[idx], sz, refTime, refGpuTime, childIdx );
}
}
2018-03-15 20:27:36 +00:00
void Worker::ReadTimelinePre0510( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int fileVer )
2018-06-17 17:05:22 +00:00
{
uint64_t sz;
f.Read( sz );
if( sz == 0 )
{
zone->SetChild( -1 );
}
else
2018-06-17 17:05:22 +00:00
{
2019-10-30 22:55:21 +00:00
const auto child = m_data.gpuChildren.size();
zone->SetChild( child );
2019-11-02 14:52:34 +00:00
m_data.gpuChildren.push_back( Vector<short_ptr<GpuEvent>>() );
Vector<short_ptr<GpuEvent>> tmp;
ReadTimelinePre0510( f, tmp, sz, refTime, refGpuTime, fileVer );
2019-10-30 22:55:21 +00:00
m_data.gpuChildren[child] = std::move( tmp );
2018-06-17 17:05:22 +00:00
}
}
#ifndef TRACY_NO_STATISTICS
void Worker::ReconstructZoneStatistics( ZoneEvent& zone, uint16_t thread )
2019-11-08 22:53:43 +00:00
{
auto it = m_data.sourceLocationZones.find( zone.SrcLoc() );
assert( it != m_data.sourceLocationZones.end() );
auto& slz = it->second;
auto& ztd = slz.zones.push_next();
ztd.SetZone( &zone );
ztd.SetThread( thread );
if( zone.End() >= 0 )
{
auto timeSpan = zone.End() - zone.Start();
if( timeSpan > 0 )
{
if( slz.min > timeSpan ) slz.min = timeSpan;
if( slz.max < timeSpan ) slz.max = timeSpan;
slz.total += timeSpan;
slz.sumSq += double( timeSpan ) * timeSpan;
if( zone.Child() >= 0 )
{
auto& children = GetZoneChildren( zone.Child() );
assert( children.is_magic() );
auto& c = *(Vector<ZoneEvent>*)( &children );
for( auto& v : c )
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
{
const auto childSpan = std::max( int64_t( 0 ), v.End() - v.Start() );
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
timeSpan -= childSpan;
}
}
if( slz.selfMin > timeSpan ) slz.selfMin = timeSpan;
if( slz.selfMax < timeSpan ) slz.selfMax = timeSpan;
slz.selfTotal += timeSpan;
}
}
2019-11-08 22:53:43 +00:00
}
2018-07-29 12:16:13 +00:00
#else
2019-11-08 22:53:43 +00:00
void Worker::CountZoneStatistics( ZoneEvent* zone )
{
2019-11-08 22:59:20 +00:00
auto cnt = GetSourceLocationZonesCnt( zone->SrcLoc() );
(*cnt)++;
}
2019-11-08 22:53:43 +00:00
#endif
2019-11-09 22:34:05 +00:00
void Worker::ReadTimeline( FileRead& f, Vector<short_ptr<ZoneEvent>>& _vec, uint64_t size, int64_t& refTime, int32_t& childIdx )
{
assert( size != 0 );
2019-11-09 22:34:05 +00:00
auto& vec = *(Vector<ZoneEvent>*)( &_vec );
vec.set_magic();
vec.reserve_exact( size, m_slab );
m_data.zonesCnt += size;
2019-11-09 22:34:05 +00:00
auto zone = vec.begin();
auto end = vec.end();
do
{
s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed );
int16_t srcloc;
f.Read( srcloc );
zone->SetSrcLoc( srcloc );
// Use zone->_end_child1 as scratch buffer for zone start time offset.
2019-11-08 23:08:26 +00:00
f.Read( &zone->_end_child1, sizeof( zone->_end_child1 ) + sizeof( zone->text ) + sizeof( zone->callstack ) + sizeof( zone->name ) );
refTime += int64_t( zone->_end_child1 );
zone->SetStart( refTime );
ReadTimeline( f, zone, refTime, childIdx );
zone->SetEnd( ReadTimeOffset( f, refTime ) );
#ifdef TRACY_NO_STATISTICS
2019-11-08 22:53:43 +00:00
CountZoneStatistics( zone );
#endif
}
2019-11-09 22:34:05 +00:00
while( ++zone != end );
}
2018-03-18 22:37:07 +00:00
2019-11-09 22:34:05 +00:00
void Worker::ReadTimelinePre0510( FileRead& f, Vector<short_ptr<ZoneEvent>>& _vec, uint64_t size, int64_t& refTime, int fileVer )
2019-08-12 17:18:17 +00:00
{
assert( fileVer <= FileVersion( 0, 5, 9 ) );
2019-08-12 17:18:17 +00:00
assert( size != 0 );
2019-11-09 22:34:05 +00:00
auto& vec = *(Vector<ZoneEvent>*)( &_vec );
vec.set_magic();
2019-08-12 17:18:17 +00:00
vec.reserve_exact( size, m_slab );
m_data.zonesCnt += size;
2019-11-09 22:34:05 +00:00
auto zone = vec.begin();
auto end = vec.end();
2019-08-12 17:18:17 +00:00
do
{
s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed );
if( fileVer >= FileVersion( 0, 5, 2 ) )
{
int16_t srcloc;
f.Read( srcloc );
zone->SetSrcLoc( srcloc );
f.Read( &zone->_end_child1, sizeof( zone->_end_child1 ) );
}
else
{
f.Read( &zone->_end_child1, sizeof( zone->_end_child1 ) );
int16_t srcloc;
f.Read( srcloc );
zone->SetSrcLoc( srcloc );
2019-11-21 20:48:35 +00:00
if( fileVer == FileVersion( 0, 5, 0 ) )
{
f.Skip( 4 );
}
else
{
f.Skip( 2 );
}
}
if( fileVer <= FileVersion( 0, 5, 7 ) )
{
__StringIdxOld str;
f.Read( str );
if( str.active )
{
zone->text.SetIdx( str.idx );
}
else
{
new ( &zone->text ) StringIdx();
}
f.Read( zone->callstack );
f.Skip( 1 );
f.Read( str );
if( str.active )
{
zone->name.SetIdx( str.idx );
}
else
{
new ( &zone->name ) StringIdx();
}
}
else
{
f.Read( &zone->text, sizeof( zone->text ) );
f.Read( &zone->callstack, sizeof( zone->callstack ) );
if( fileVer <= FileVersion( 0, 5, 8 ) )
{
f.Skip( 1 );
}
f.Read( &zone->name, sizeof( zone->name ) );
}
refTime += zone->_end_child1;
zone->SetStart( refTime - m_data.baseTime );
ReadTimelinePre0510( f, zone, refTime, fileVer );
int64_t end = ReadTimeOffset( f, refTime );
if( end >= 0 ) end -= m_data.baseTime;
zone->SetEnd( end );
2019-08-12 17:18:17 +00:00
#ifdef TRACY_NO_STATISTICS
2019-11-08 22:53:43 +00:00
CountZoneStatistics( zone );
2019-08-12 17:18:17 +00:00
#endif
}
2019-11-09 22:34:05 +00:00
while( ++zone != end );
2019-08-12 17:18:17 +00:00
}
2019-11-10 00:36:13 +00:00
void Worker::ReadTimeline( FileRead& f, Vector<short_ptr<GpuEvent>>& _vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx )
{
assert( size != 0 );
2019-11-10 00:36:13 +00:00
auto& vec = *(Vector<GpuEvent>*)( &_vec );
vec.set_magic();
vec.reserve_exact( size, m_slab );
2019-10-13 12:13:04 +00:00
m_data.gpuCnt += size;
2019-11-10 00:36:13 +00:00
auto zone = vec.begin();
auto end = vec.end();
do
{
s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed );
int64_t tcpu, tgpu;
int16_t srcloc;
2019-11-08 23:43:06 +00:00
f.Read3( tcpu, tgpu, srcloc );
zone->SetSrcLoc( srcloc );
uint16_t thread;
2019-11-08 23:43:06 +00:00
f.Read2( zone->callstack, thread );
zone->SetThread( thread );
refTime += tcpu;
refGpuTime += tgpu;
zone->SetCpuStart( refTime );
zone->SetGpuStart( refGpuTime );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
ReadTimeline( f, zone, refTime, refGpuTime, childIdx );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
f.Read2( tcpu, tgpu );
refTime += tcpu;
refGpuTime += tgpu;
zone->SetCpuEnd( refTime );
zone->SetGpuEnd( refGpuTime );
}
2019-11-10 00:36:13 +00:00
while( ++zone != end );
}
2019-11-10 00:36:13 +00:00
void Worker::ReadTimelinePre0510( FileRead& f, Vector<short_ptr<GpuEvent>>& _vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime, int fileVer )
2018-06-17 17:05:22 +00:00
{
assert( size != 0 );
2019-11-10 00:36:13 +00:00
auto& vec = *(Vector<GpuEvent>*)( &_vec );
vec.set_magic();
vec.reserve_exact( size, m_slab );
2019-10-13 12:13:04 +00:00
m_data.gpuCnt += size;
2019-11-10 00:36:13 +00:00
auto zone = vec.begin();
auto end = vec.end();
do
2018-06-17 17:05:22 +00:00
{
s_loadProgress.subProgress.fetch_add( 1, std::memory_order_relaxed );
2018-06-17 17:05:22 +00:00
2019-11-21 20:48:35 +00:00
if( fileVer <= FileVersion( 0, 5, 1 ) )
{
int64_t tcpu, tgpu;
f.Read2( tcpu, tgpu );
int16_t srcloc;
f.Read( srcloc );
zone->SetSrcLoc( srcloc );
f.Skip( 2 );
f.Read( zone->callstack );
f.Skip( 1 );
uint16_t thread;
f.Read( thread );
zone->SetThread( thread );
refTime += tcpu;
refGpuTime += tgpu;
tgpu = refGpuTime;
if( tgpu != std::numeric_limits<int64_t>::max() ) tgpu -= m_data.baseTime;
zone->SetCpuStart( refTime - m_data.baseTime );
zone->SetGpuStart( tgpu );
}
else
{
int64_t tcpu, tgpu;
f.Read2( tcpu, tgpu );
int16_t srcloc;
f.Read( srcloc );
zone->SetSrcLoc( srcloc );
f.Read( &zone->callstack, sizeof( zone->callstack ) );
if( fileVer <= FileVersion( 0, 5, 8 ) )
{
f.Skip( 1 );
}
uint16_t thread;
f.Read( thread );
zone->SetThread( thread );
refTime += tcpu;
refGpuTime += tgpu;
zone->SetCpuStart( refTime );
zone->SetGpuStart( refGpuTime );
}
ReadTimelinePre0510( f, zone, refTime, refGpuTime, fileVer );
2019-11-21 20:48:35 +00:00
int64_t cpuEnd = ReadTimeOffset( f, refTime );
if( cpuEnd > 0 ) cpuEnd -= m_data.baseTime;
zone->SetCpuEnd( cpuEnd );
int64_t gpuEnd = ReadTimeOffset( f, refGpuTime );
if( gpuEnd > 0 ) gpuEnd -= m_data.baseTime;
zone->SetGpuEnd( gpuEnd );
2018-06-17 17:05:22 +00:00
}
2019-11-10 00:36:13 +00:00
while( ++zone != end );
2018-06-17 17:05:22 +00:00
}
2019-08-01 21:14:09 +00:00
void Worker::Disconnect()
{
Query( ServerQueryDisconnect, 0 );
m_disconnect = true;
}
void Worker::Write( FileWrite& f )
{
2018-04-21 11:45:48 +00:00
f.Write( FileHeader, sizeof( FileHeader ) );
f.Write( &m_delay, sizeof( m_delay ) );
f.Write( &m_resolution, sizeof( m_resolution ) );
f.Write( &m_timerMul, sizeof( m_timerMul ) );
f.Write( &m_data.lastTime, sizeof( m_data.lastTime ) );
2018-07-10 20:56:41 +00:00
f.Write( &m_data.frameOffset, sizeof( m_data.frameOffset ) );
2019-08-17 20:19:04 +00:00
f.Write( &m_pid, sizeof( m_pid ) );
uint64_t sz = m_captureName.size();
f.Write( &sz, sizeof( sz ) );
f.Write( m_captureName.c_str(), sz );
sz = m_captureProgram.size();
f.Write( &sz, sizeof( sz ) );
f.Write( m_captureProgram.c_str(), sz );
f.Write( &m_captureTime, sizeof( m_captureTime ) );
2018-08-19 16:28:48 +00:00
sz = m_hostInfo.size();
f.Write( &sz, sizeof( sz ) );
f.Write( m_hostInfo.c_str(), sz );
sz = m_data.cpuTopology.size();
f.Write( &sz, sizeof( sz ) );
for( auto& package : m_data.cpuTopology )
{
sz = package.second.size();
f.Write( &package.first, sizeof( package.first ) );
f.Write( &sz, sizeof( sz ) );
for( auto& core : package.second )
{
sz = core.second.size();
f.Write( &core.first, sizeof( core.first ) );
f.Write( &sz, sizeof( sz ) );
for( auto& thread : core.second )
{
f.Write( &thread, sizeof( thread ) );
}
}
}
2019-03-26 20:41:44 +00:00
f.Write( &m_data.crashEvent, sizeof( m_data.crashEvent ) );
2018-08-20 00:27:24 +00:00
2018-08-04 17:47:09 +00:00
sz = m_data.frames.Data().size();
f.Write( &sz, sizeof( sz ) );
2018-08-04 17:47:09 +00:00
for( auto& fd : m_data.frames.Data() )
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
2018-08-04 17:47:09 +00:00
f.Write( &fd->name, sizeof( fd->name ) );
2018-08-05 00:09:59 +00:00
f.Write( &fd->continuous, sizeof( fd->continuous ) );
2018-08-04 17:47:09 +00:00
sz = fd->frames.size();
f.Write( &sz, sizeof( sz ) );
2018-08-05 00:09:59 +00:00
if( fd->continuous )
{
for( auto& fe : fd->frames )
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
WriteTimeOffset( f, refTime, fe.start );
2019-06-06 21:08:19 +00:00
f.Write( &fe.frameImage, sizeof( fe.frameImage ) );
2018-08-05 00:09:59 +00:00
}
}
else
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
for( auto& fe : fd->frames )
{
WriteTimeOffset( f, refTime, fe.start );
WriteTimeOffset( f, refTime, fe.end );
2019-06-06 21:08:19 +00:00
f.Write( &fe.frameImage, sizeof( fe.frameImage ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
}
2018-08-05 00:09:59 +00:00
}
2018-08-04 17:47:09 +00:00
}
sz = m_data.stringData.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.stringData )
{
uint64_t ptr = (uint64_t)v;
f.Write( &ptr, sizeof( ptr ) );
sz = strlen( v );
f.Write( &sz, sizeof( sz ) );
f.Write( v, sz );
}
sz = m_data.strings.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.strings )
{
f.Write( &v.first, sizeof( v.first ) );
uint64_t ptr = (uint64_t)v.second;
f.Write( &ptr, sizeof( ptr ) );
}
sz = m_data.threadNames.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.threadNames )
{
f.Write( &v.first, sizeof( v.first ) );
uint64_t ptr = (uint64_t)v.second;
f.Write( &ptr, sizeof( ptr ) );
}
2019-08-16 17:24:38 +00:00
sz = m_data.externalNames.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.externalNames )
{
f.Write( &v.first, sizeof( v.first ) );
2019-08-16 17:49:16 +00:00
uint64_t ptr = (uint64_t)v.second.first;
f.Write( &ptr, sizeof( ptr ) );
ptr = (uint64_t)v.second.second;
2019-08-16 17:24:38 +00:00
f.Write( &ptr, sizeof( ptr ) );
}
m_data.localThreadCompress.Save( f );
m_data.externalThreadCompress.Save( f );
sz = m_data.sourceLocation.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.sourceLocation )
{
f.Write( &v.first, sizeof( v.first ) );
f.Write( &v.second, sizeof( SourceLocationBase ) );
}
sz = m_data.sourceLocationExpand.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.sourceLocationExpand )
{
f.Write( &v, sizeof( v ) );
}
sz = m_data.sourceLocationPayload.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.sourceLocationPayload )
{
f.Write( v, sizeof( SourceLocationBase ) );
}
#ifndef TRACY_NO_STATISTICS
sz = m_data.sourceLocationZones.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.sourceLocationZones )
{
int16_t id = v.first;
uint64_t cnt = v.second.zones.size();
f.Write( &id, sizeof( id ) );
f.Write( &cnt, sizeof( cnt ) );
}
#else
sz = m_data.sourceLocationZonesCnt.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.sourceLocationZonesCnt )
{
int16_t id = v.first;
uint64_t cnt = v.second;
f.Write( &id, sizeof( id ) );
f.Write( &cnt, sizeof( cnt ) );
}
#endif
sz = m_data.lockMap.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.lockMap )
{
f.Write( &v.first, sizeof( v.first ) );
f.Write( &v.second->srcloc, sizeof( v.second->srcloc ) );
f.Write( &v.second->type, sizeof( v.second->type ) );
f.Write( &v.second->valid, sizeof( v.second->valid ) );
f.Write( &v.second->timeAnnounce, sizeof( v.second->timeAnnounce ) );
f.Write( &v.second->timeTerminate, sizeof( v.second->timeTerminate ) );
sz = v.second->threadList.size();
f.Write( &sz, sizeof( sz ) );
for( auto& t : v.second->threadList )
{
f.Write( &t, sizeof( t ) );
}
int64_t refTime = v.second->timeAnnounce;
sz = v.second->timeline.size();
f.Write( &sz, sizeof( sz ) );
for( auto& lev : v.second->timeline )
{
WriteTimeOffset( f, refTime, lev.ptr->Time() );
const int16_t srcloc = lev.ptr->SrcLoc();
f.Write( &srcloc, sizeof( srcloc ) );
f.Write( &lev.ptr->thread, sizeof( lev.ptr->thread ) );
f.Write( &lev.ptr->type, sizeof( lev.ptr->type ) );
}
}
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
sz = m_data.messages.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.messages )
{
2019-11-02 15:32:42 +00:00
const auto ptr = (uint64_t)(MessageData*)v;
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
f.Write( &ptr, sizeof( ptr ) );
WriteTimeOffset( f, refTime, v->time );
f.Write( &v->ref, sizeof( v->ref ) );
f.Write( &v->color, sizeof( v->color ) );
2019-11-14 23:42:44 +00:00
f.Write( &v->callstack, sizeof( v->callstack ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
}
}
sz = 0;
for( auto& v : m_data.threads ) sz += v->count;
f.Write( &sz, sizeof( sz ) );
sz = m_data.zoneChildren.size();
f.Write( &sz, sizeof( sz ) );
sz = m_data.threads.size();
f.Write( &sz, sizeof( sz ) );
for( auto& thread : m_data.threads )
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
f.Write( &thread->id, sizeof( thread->id ) );
f.Write( &thread->count, sizeof( thread->count ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
WriteTimeline( f, thread->timeline, refTime );
sz = thread->messages.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : thread->messages )
{
2019-11-02 15:17:20 +00:00
auto ptr = uint64_t( (MessageData*)v );
f.Write( &ptr, sizeof( ptr ) );
}
}
sz = 0;
for( auto& v : m_data.gpuData ) sz += v->count;
f.Write( &sz, sizeof( sz ) );
sz = m_data.gpuChildren.size();
f.Write( &sz, sizeof( sz ) );
sz = m_data.gpuData.size();
f.Write( &sz, sizeof( sz ) );
for( auto& ctx : m_data.gpuData )
{
f.Write( &ctx->thread, sizeof( ctx->thread ) );
f.Write( &ctx->accuracyBits, sizeof( ctx->accuracyBits ) );
f.Write( &ctx->count, sizeof( ctx->count ) );
f.Write( &ctx->period, sizeof( ctx->period ) );
2019-09-23 15:27:49 +00:00
sz = ctx->threadData.size();
f.Write( &sz, sizeof( sz ) );
for( auto& td : ctx->threadData )
{
int64_t refTime = 0;
int64_t refGpuTime = 0;
uint64_t tid = td.first;
f.Write( &tid, sizeof( tid ) );
WriteTimeline( f, td.second.timeline, refTime, refGpuTime );
}
}
2018-08-04 14:33:03 +00:00
sz = m_data.plots.Data().size();
2019-02-21 21:53:26 +00:00
for( auto& plot : m_data.plots.Data() ) { if( plot->type == PlotType::Memory ) sz--; }
f.Write( &sz, sizeof( sz ) );
2018-08-04 14:33:03 +00:00
for( auto& plot : m_data.plots.Data() )
{
2019-02-21 21:53:26 +00:00
if( plot->type == PlotType::Memory ) continue;
f.Write( &plot->type, sizeof( plot->type ) );
f.Write( &plot->format, sizeof( plot->format ) );
f.Write( &plot->name, sizeof( plot->name ) );
f.Write( &plot->min, sizeof( plot->min ) );
f.Write( &plot->max, sizeof( plot->max ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
sz = plot->data.size();
f.Write( &sz, sizeof( sz ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
for( auto& v : plot->data )
{
WriteTimeOffset( f, refTime, v.time.Val() );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
f.Write( &v.val, sizeof( v.val ) );
}
}
2018-04-02 00:05:16 +00:00
{
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
int64_t refTime = 0;
sz = m_data.memory.data.size();
f.Write( &sz, sizeof( sz ) );
sz = m_data.memory.active.size();
f.Write( &sz, sizeof( sz ) );
sz = m_data.memory.frees.size();
f.Write( &sz, sizeof( sz ) );
for( auto& mem : m_data.memory.data )
{
const auto ptr = mem.Ptr();
const auto size = mem.Size();
const Int24 csAlloc = mem.CsAlloc();
f.Write( &ptr, sizeof( ptr ) );
f.Write( &size, sizeof( size ) );
f.Write( &csAlloc, sizeof( csAlloc ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
f.Write( &mem.csFree, sizeof( mem.csFree ) );
int64_t timeAlloc = mem.TimeAlloc();
uint16_t threadAlloc = mem.ThreadAlloc();
int64_t timeFree = mem.TimeFree();
uint16_t threadFree = mem.ThreadFree();
WriteTimeOffset( f, refTime, timeAlloc );
int64_t freeOffset = timeFree < 0 ? timeFree : timeFree - timeAlloc;
f.Write( &freeOffset, sizeof( freeOffset ) );
f.Write( &threadAlloc, sizeof( threadAlloc ) );
f.Write( &threadFree, sizeof( threadFree ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
}
f.Write( &m_data.memory.high, sizeof( m_data.memory.high ) );
f.Write( &m_data.memory.low, sizeof( m_data.memory.low ) );
f.Write( &m_data.memory.usage, sizeof( m_data.memory.usage ) );
2018-04-02 00:05:16 +00:00
}
2018-06-19 19:39:52 +00:00
2018-06-19 19:52:54 +00:00
sz = m_data.callstackPayload.size() - 1;
2018-06-19 19:39:52 +00:00
f.Write( &sz, sizeof( sz ) );
2018-06-19 23:54:27 +00:00
for( size_t i=1; i<=sz; i++ )
2018-06-19 19:39:52 +00:00
{
2018-06-19 19:52:54 +00:00
auto cs = m_data.callstackPayload[i];
2018-06-19 19:39:52 +00:00
uint8_t csz = cs->size();
f.Write( &csz, sizeof( csz ) );
f.Write( cs->data(), sizeof( CallstackFrameId ) * csz );
2018-06-19 19:39:52 +00:00
}
2018-06-19 23:59:25 +00:00
sz = m_data.callstackFrameMap.size();
f.Write( &sz, sizeof( sz ) );
for( auto& frame : m_data.callstackFrameMap )
{
f.Write( &frame.first, sizeof( CallstackFrameId ) );
f.Write( &frame.second->size, sizeof( frame.second->size ) );
f.Write( frame.second->data, sizeof( CallstackFrame ) * frame.second->size );
2018-06-19 23:59:25 +00:00
}
2019-06-06 21:08:19 +00:00
2019-07-12 16:45:35 +00:00
sz = m_data.appInfo.size();
f.Write( &sz, sizeof( sz ) );
f.Write( m_data.appInfo.data(), sizeof( m_data.appInfo[0] ) * sz );
2019-06-06 21:08:19 +00:00
sz = m_data.frameImage.size();
f.Write( &sz, sizeof( sz ) );
for( auto& fi : m_data.frameImage )
{
f.Write( &fi->w, sizeof( fi->w ) );
f.Write( &fi->h, sizeof( fi->h ) );
2019-06-12 13:28:32 +00:00
f.Write( &fi->flip, sizeof( fi->flip ) );
2019-06-08 10:17:18 +00:00
const auto image = UnpackFrameImage( *fi );
f.Write( image, fi->w * fi->h / 2 );
2019-06-06 21:08:19 +00:00
}
2019-08-12 22:56:57 +00:00
// Only save context switches relevant to active threads.
std::vector<flat_hash_map<uint64_t, ContextSwitch*, nohash<uint64_t>>::const_iterator> ctxValid;
ctxValid.reserve( m_data.ctxSwitch.size() );
for( auto it = m_data.ctxSwitch.begin(); it != m_data.ctxSwitch.end(); ++it )
{
if( m_data.localThreadCompress.Exists( it->first ) )
2019-08-12 22:56:57 +00:00
{
ctxValid.emplace_back( it );
}
}
sz = ctxValid.size();
f.Write( &sz, sizeof( sz ) );
for( auto& ctx : ctxValid )
{
f.Write( &ctx->first, sizeof( ctx->first ) );
sz = ctx->second->v.size();
f.Write( &sz, sizeof( sz ) );
int64_t refTime = 0;
for( auto& cs : ctx->second->v )
{
WriteTimeOffset( f, refTime, cs.WakeupVal() );
WriteTimeOffset( f, refTime, cs.Start() );
WriteTimeOffset( f, refTime, cs.End() );
uint8_t cpu = cs.Cpu();
int8_t reason = cs.Reason();
int8_t state = cs.State();
f.Write( &cpu, sizeof( cpu ) );
f.Write( &reason, sizeof( reason ) );
f.Write( &state, sizeof( state ) );
2019-08-12 22:56:57 +00:00
}
}
2019-08-16 14:51:02 +00:00
sz = GetContextSwitchPerCpuCount();
f.Write( &sz, sizeof( sz ) );
for( int i=0; i<256; i++ )
{
sz = m_data.cpuData[i].cs.size();
f.Write( &sz, sizeof( sz ) );
int64_t refTime = 0;
for( auto& cx : m_data.cpuData[i].cs )
{
WriteTimeOffset( f, refTime, cx.Start() );
WriteTimeOffset( f, refTime, cx.End() );
uint16_t thread = cx.Thread();
2019-08-16 14:51:02 +00:00
f.Write( &thread, sizeof( thread ) );
}
}
2019-08-17 20:36:21 +00:00
sz = m_data.tidToPid.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.tidToPid )
{
f.Write( &v.first, sizeof( v.first ) );
f.Write( &v.second, sizeof( v.second ) );
}
2019-08-17 23:53:38 +00:00
sz = m_data.cpuThreadData.size();
f.Write( &sz, sizeof( sz ) );
for( auto& v : m_data.cpuThreadData )
{
f.Write( &v.first, sizeof( v.first ) );
f.Write( &v.second, sizeof( v.second ) );
}
}
2019-11-02 15:17:20 +00:00
void Worker::WriteTimeline( FileWrite& f, const Vector<short_ptr<ZoneEvent>>& vec, int64_t& refTime )
{
uint64_t sz = vec.size();
f.Write( &sz, sizeof( sz ) );
if( vec.is_magic() )
{
WriteTimelineImpl<VectorAdapterDirect<ZoneEvent>>( f, *(Vector<ZoneEvent>*)( &vec ), refTime );
}
else
{
WriteTimelineImpl<VectorAdapterPointer<ZoneEvent>>( f, vec, refTime );
}
}
template<typename Adapter, typename V>
void Worker::WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime )
{
Adapter a;
for( auto& val : vec )
{
auto& v = a(val);
int16_t srcloc = v.SrcLoc();
f.Write( &srcloc, sizeof( srcloc ) );
int64_t start = v.Start();
WriteTimeOffset( f, refTime, start );
f.Write( &v.text, sizeof( v.text ) );
f.Write( &v.callstack, sizeof( v.callstack ) );
f.Write( &v.name, sizeof( v.name ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
if( v.Child() < 0 )
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
{
const uint64_t sz = 0;
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
f.Write( &sz, sizeof( sz ) );
}
else
{
WriteTimeline( f, GetZoneChildren( v.Child() ), refTime );
Store children vectors in a separate data collection. This reduces per-zone memory cost by 9 bytes if there are no children and increases it by 4 bytes, if there are children. This is universally a better solution, as the following data shows: +++ /home/wolf/desktop/tracy-old/android.tracy +++ Vectors: 2794480 Size 0: 2373070 (84.92%) Size 1: 70237 (2.51%) Size 2+: 351173 (12.57%) +++ /home/wolf/desktop/tracy-old/asset-new.tracy +++ Vectors: 1799227 Size 0: 1482691 (82.41%) Size 1: 93272 (5.18%) Size 2+: 223264 (12.41%) +++ /home/wolf/desktop/tracy-old/asset-new-id.tracy +++ Vectors: 1977996 Size 0: 1640817 (82.95%) Size 1: 97198 (4.91%) Size 2+: 239981 (12.13%) +++ /home/wolf/desktop/tracy-old/asset-old.tracy +++ Vectors: 1782395 Size 0: 1471437 (82.55%) Size 1: 88813 (4.98%) Size 2+: 222145 (12.46%) +++ /home/wolf/desktop/tracy-old/big.tracy +++ Vectors: 180794047 Size 0: 172696094 (95.52%) Size 1: 2799772 (1.55%) Size 2+: 5298181 (2.93%) +++ /home/wolf/desktop/tracy-old/darkrl.tracy +++ Vectors: 12014129 Size 0: 11611324 (96.65%) Size 1: 134980 (1.12%) Size 2+: 267825 (2.23%) +++ /home/wolf/desktop/tracy-old/mem.tracy +++ Vectors: 383097 Size 0: 321932 (84.03%) Size 1: 854 (0.22%) Size 2+: 60311 (15.74%) +++ /home/wolf/desktop/tracy-old/new.tracy +++ Vectors: 77536 Size 0: 63035 (81.30%) Size 1: 8886 (11.46%) Size 2+: 5615 (7.24%) +++ /home/wolf/desktop/tracy-old/selfprofile.tracy +++ Vectors: 22940871 Size 0: 22704868 (98.97%) Size 1: 73000 (0.32%) Size 2+: 163003 (0.71%) +++ /home/wolf/desktop/tracy-old/tbrowser.tracy +++ Vectors: 962682 Size 0: 695380 (72.23%) Size 1: 43007 (4.47%) Size 2+: 224295 (23.30%) +++ /home/wolf/desktop/tracy-old/virtualfile_hc.tracy +++ Vectors: 529170 Size 0: 449386 (84.92%) Size 1: 15694 (2.97%) Size 2+: 64090 (12.11%) +++ /home/wolf/desktop/tracy-old/zfile_hc.tracy +++ Vectors: 264849 Size 0: 220589 (83.29%) Size 1: 9386 (3.54%) Size 2+: 34874 (13.17%)
2018-07-22 14:05:50 +00:00
}
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
WriteTimeOffset( f, refTime, v.End() );
}
}
2019-11-02 14:52:34 +00:00
void Worker::WriteTimeline( FileWrite& f, const Vector<short_ptr<GpuEvent>>& vec, int64_t& refTime, int64_t& refGpuTime )
{
uint64_t sz = vec.size();
f.Write( &sz, sizeof( sz ) );
if( vec.is_magic() )
{
WriteTimelineImpl<VectorAdapterDirect<GpuEvent>>( f, *(Vector<GpuEvent>*)( &vec ), refTime, refGpuTime );
}
else
{
WriteTimelineImpl<VectorAdapterPointer<GpuEvent>>( f, vec, refTime, refGpuTime );
}
}
template<typename Adapter, typename V>
void Worker::WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime, int64_t& refGpuTime )
{
Adapter a;
for( auto& val : vec )
{
auto& v = a(val);
WriteTimeOffset( f, refTime, v.CpuStart() );
WriteTimeOffset( f, refGpuTime, v.GpuStart() );
const int16_t srcloc = v.SrcLoc();
f.Write( &srcloc, sizeof( srcloc ) );
f.Write( &v.callstack, sizeof( v.callstack ) );
const uint16_t thread = v.Thread();
f.Write( &thread, sizeof( thread ) );
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
if( v.Child() < 0 )
{
const uint64_t sz = 0;
f.Write( &sz, sizeof( sz ) );
}
else
{
WriteTimeline( f, GetGpuChildren( v.Child() ), refTime, refGpuTime );
}
Store time deltas, instead of absolute time in trace dumps. This change greatly reduces the size of saved dumps, but increase the cost of processing during loading. One notable outlier in the dataset below is mem.tracy, which increased in size, even if changes in the memory dump saving scheme decrease size of the other traces. 041/aa.tracy (0.4.1) {18987 KB} -> 042/aa.tracy (0.4.2) {10140 KB} 53.40% size change 041/android.tracy (0.4.1) {696753 KB} -> 042/android.tracy (0.4.2) {542738 KB} 77.90% size change 041/asset-new.tracy (0.4.1) {97163 KB} -> 042/asset-new.tracy (0.4.2) {78402 KB} 80.69% size change 041/asset-new-id.tracy (0.4.1) {105683 KB} -> 042/asset-new-id.tracy (0.4.2) {84341 KB} 79.81% size change 041/asset-old.tracy (0.4.1) {100205 KB} -> 042/asset-old.tracy (0.4.2) {80688 KB} 80.52% size change 041/big.tracy (0.4.1) {2246014 KB} -> 042/big.tracy (0.4.2) {943083 KB} 41.99% size change 041/crash.tracy (0.4.1) {143 KB} -> 042/crash.tracy (0.4.2) {131 KB} 91.39% size change 041/crash2.tracy (0.4.1) {3411 KB} -> 042/crash2.tracy (0.4.2) {1425 KB} 41.80% size change 041/darkrl.tracy (0.4.1) {31818 KB} -> 042/darkrl.tracy (0.4.2) {15897 KB} 49.96% size change 041/darkrl2.tracy (0.4.1) {18778 KB} -> 042/darkrl2.tracy (0.4.2) {8002 KB} 42.62% size change 041/darkrl-old.tracy (0.4.1) {151346 KB} -> 042/darkrl-old.tracy (0.4.2) {67945 KB} 44.89% size change 041/deadlock.tracy (0.4.1) {53 KB} -> 042/deadlock.tracy (0.4.2) {52 KB} 98.55% size change 041/gn-opengl.tracy (0.4.1) {45860 KB} -> 042/gn-opengl.tracy (0.4.2) {30983 KB} 67.56% size change 041/gn-vulkan.tracy (0.4.1) {45618 KB} -> 042/gn-vulkan.tracy (0.4.2) {31349 KB} 68.72% size change 041/long.tracy (0.4.1) {1583550 KB} -> 042/long.tracy (0.4.2) {1225316 KB} 77.38% size change 041/mem.tracy (0.4.1) {1243058 KB} -> 042/mem.tracy (0.4.2) {1369291 KB} 110.15% size change 041/multi.tracy (0.4.1) {14519 KB} -> 042/multi.tracy (0.4.2) {8110 KB} 55.86% size change 041/new.tracy (0.4.1) {1439 KB} -> 042/new.tracy (0.4.2) {1108 KB} 77.01% size change 041/q3bsp-mt.tracy (0.4.1) {1414323 KB} -> 042/q3bsp-mt.tracy (0.4.2) {949855 KB} 67.16% size change 041/q3bsp-st.tracy (0.4.1) {301334 KB} -> 042/q3bsp-st.tracy (0.4.2) {240347 KB} 79.76% size change 041/selfprofile.tracy (0.4.1) {399648 KB} -> 042/selfprofile.tracy (0.4.2) {197713 KB} 49.47% size change 041/tbrowser.tracy (0.4.1) {13052 KB} -> 042/tbrowser.tracy (0.4.2) {9503 KB} 72.81% size change 041/test.tracy (0.4.1) {60309 KB} -> 042/test.tracy (0.4.2) {40700 KB} 67.49% size change 041/virtualfile_hc.tracy (0.4.1) {108967 KB} -> 042/virtualfile_hc.tracy (0.4.2) {72839 KB} 66.85% size change 041/zfile_hc.tracy (0.4.1) {58814 KB} -> 042/zfile_hc.tracy (0.4.2) {39608 KB} 67.35% size change
2018-12-30 22:06:03 +00:00
WriteTimeOffset( f, refTime, v.CpuEnd() );
WriteTimeOffset( f, refGpuTime, v.GpuEnd() );
}
}
static const char* s_failureReasons[] = {
"<unknown reason>",
"Invalid order of zone begin and end events.",
"Zone text transfer destination doesn't match active zone.",
"Zone name transfer destination doesn't match active zone.",
"Memory free event without a matching allocation.",
"Discontinuous frame begin/end mismatch.",
"Frame image offset is invalid.",
"Multiple frame images were sent for a single frame.",
};
static_assert( sizeof( s_failureReasons ) / sizeof( *s_failureReasons ) == (int)Worker::Failure::NUM_FAILURES, "Missing failure reason description." );
const char* Worker::GetFailureString( Worker::Failure failure )
{
return s_failureReasons[(int)failure];
}
void Worker::PackFrameImage( char*& buf, size_t& bufsz, const char* image, uint32_t inBytes, uint32_t& csz ) const
{
const auto maxout = LZ4_COMPRESSBOUND( inBytes );
if( bufsz < maxout )
{
bufsz = maxout;
delete[] buf;
buf = new char[maxout];
}
const auto outsz = LZ4_compress_default( image, buf, inBytes, maxout );
csz = uint32_t( outsz );
}
const char* Worker::PackFrameImage( const char* image, uint32_t inBytes, uint32_t& csz )
2019-06-08 10:17:18 +00:00
{
const auto maxout = LZ4_COMPRESSBOUND( inBytes );
if( m_frameImageCompressedBufferSize < maxout )
2019-06-08 10:17:18 +00:00
{
m_frameImageCompressedBufferSize = maxout;
delete[] m_frameImageCompressedBuffer;
m_frameImageCompressedBuffer = new char[maxout];
2019-06-08 10:17:18 +00:00
}
const auto outsz = LZ4_compress_default( image, m_frameImageCompressedBuffer, inBytes, maxout );
2019-06-08 10:17:18 +00:00
csz = uint32_t( outsz );
auto ptr = (char*)m_slab.AllocBig( outsz );
memcpy( ptr, m_frameImageCompressedBuffer, outsz );
2019-06-08 10:17:18 +00:00
return ptr;
}
const char* Worker::UnpackFrameImage( const FrameImage& image )
{
const auto outsz = size_t( image.w ) * size_t( image.h ) / 2;
if( m_frameImageCompressedBufferSize < outsz )
2019-06-08 10:17:18 +00:00
{
m_frameImageCompressedBufferSize = outsz;
delete[] m_frameImageCompressedBuffer;
m_frameImageCompressedBuffer = new char[outsz];
2019-06-08 10:17:18 +00:00
}
LZ4_decompress_safe( image.ptr, m_frameImageCompressedBuffer, image.csz, outsz );
return m_frameImageCompressedBuffer;
2019-06-08 10:17:18 +00:00
}
void Worker::SetParameter( size_t paramIdx, int32_t val )
{
assert( paramIdx < m_params.size() );
m_params[paramIdx].val = val;
const auto idx = uint64_t( m_params[paramIdx].idx );
const auto v = uint64_t( uint32_t( val ) );
Query( ServerQueryParameter, ( idx << 32 ) | val );
}
2019-11-29 21:46:57 +00:00
const Worker::CpuThreadTopology* Worker::GetThreadTopology( uint32_t cpuThread ) const
{
auto it = m_data.cpuTopologyMap.find( cpuThread );
if( it == m_data.cpuTopologyMap.end() ) return nullptr;
return &it->second;
}
}