Zone ids are unnecessary.

This commit is contained in:
Bartosz Taudul 2017-10-03 16:41:32 +02:00
parent 3fcf39ec58
commit d1edd30ca6
6 changed files with 89 additions and 76 deletions

View File

@ -159,24 +159,26 @@ bool Profiler::SendString( uint64_t str, const char* ptr, QueueType type )
{ {
assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData ); assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData );
QueueHeader hdr; QueueItem item;
hdr.type = type; item.hdr.type = type;
hdr.id = str; item.stringTransfer.ptr = str;
const auto isz = QueueDataSize[item.hdr.idx];
auto buf = m_buffer + m_bufferOffset; auto buf = m_buffer + m_bufferOffset;
memcpy( buf, &hdr, sizeof( hdr ) ); memcpy( buf, &item, isz );
auto len = strlen( ptr ); auto len = strlen( ptr );
assert( len < TargetFrameSize - sizeof( hdr ) - sizeof( uint16_t ) ); assert( len < TargetFrameSize - isz - sizeof( uint16_t ) );
assert( len <= std::numeric_limits<uint16_t>::max() ); assert( len <= std::numeric_limits<uint16_t>::max() );
uint16_t l16 = len; uint16_t l16 = len;
memcpy( buf + sizeof( hdr ), &l16, sizeof( l16 ) ); memcpy( buf + isz, &l16, sizeof( l16 ) );
memcpy( buf + sizeof( hdr ) + sizeof( l16 ), ptr, l16 ); memcpy( buf + isz + sizeof( l16 ), ptr, l16 );
m_bufferOffset += sizeof( hdr ) + sizeof( l16 ) + l16; m_bufferOffset += isz + sizeof( l16 ) + l16;
if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0; if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0;
return SendData( buf, sizeof( hdr ) + sizeof( l16 ) + l16 ); return SendData( buf, isz + sizeof( l16 ) + l16 );
} }
void Profiler::SendSourceLocation( uint64_t ptr ) void Profiler::SendSourceLocation( uint64_t ptr )
@ -184,7 +186,7 @@ void Profiler::SendSourceLocation( uint64_t ptr )
auto srcloc = (const SourceLocation*)ptr; auto srcloc = (const SourceLocation*)ptr;
QueueItem item; QueueItem item;
item.hdr.type = QueueType::SourceLocation; item.hdr.type = QueueType::SourceLocation;
item.hdr.id = ptr; item.srcloc.ptr = ptr;
item.srcloc.file = (uint64_t)srcloc->file; item.srcloc.file = (uint64_t)srcloc->file;
item.srcloc.function = (uint64_t)srcloc->function; item.srcloc.function = (uint64_t)srcloc->function;
item.srcloc.line = srcloc->line; item.srcloc.line = srcloc->line;
@ -278,22 +280,20 @@ void Profiler::CalibrateDelay()
for( int i=0; i<Iterations; i++ ) for( int i=0; i<Iterations; i++ )
{ {
static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 };
const auto id = GetNewId();
{ {
Magic magic; Magic magic;
auto item = s_queue.enqueue_begin( ptoken, magic ); auto item = s_queue.enqueue_begin( ptoken, magic );
item->hdr.type = QueueType::ZoneBegin; item->hdr.type = QueueType::ZoneBegin;
item->hdr.id = id; item->zoneBegin.thread = GetThreadHandle();
item->zoneBegin.time = GetTime( item->zoneBegin.cpu ); item->zoneBegin.time = GetTime( item->zoneBegin.cpu );
item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location; item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location;
item->zoneBegin.thread = GetThreadHandle();
s_queue.enqueue_finish( ptoken, magic ); s_queue.enqueue_finish( ptoken, magic );
} }
{ {
Magic magic; Magic magic;
auto item = s_queue.enqueue_begin( ptoken, magic ); auto item = s_queue.enqueue_begin( ptoken, magic );
item->hdr.type = QueueType::ZoneEnd; item->hdr.type = QueueType::ZoneEnd;
item->hdr.id = id; item->zoneEnd.thread = 0;
item->zoneEnd.time = GetTime( item->zoneEnd.cpu ); item->zoneEnd.time = GetTime( item->zoneEnd.cpu );
s_queue.enqueue_finish( ptoken, magic ); s_queue.enqueue_finish( ptoken, magic );
} }
@ -308,22 +308,20 @@ void Profiler::CalibrateDelay()
for( int i=0; i<Iterations; i++ ) for( int i=0; i<Iterations; i++ )
{ {
static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; static const tracy::SourceLocation __tracy_source_location { __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 };
const auto id = GetNewId();
{ {
Magic magic; Magic magic;
auto item = s_queue.enqueue_begin( ptoken, magic ); auto item = s_queue.enqueue_begin( ptoken, magic );
item->hdr.type = QueueType::ZoneBegin; item->hdr.type = QueueType::ZoneBegin;
item->hdr.id = id; item->zoneBegin.thread = GetThreadHandle();
item->zoneBegin.time = GetTime( item->zoneBegin.cpu ); item->zoneBegin.time = GetTime( item->zoneBegin.cpu );
item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location; item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location;
item->zoneBegin.thread = GetThreadHandle();
s_queue.enqueue_finish( ptoken, magic ); s_queue.enqueue_finish( ptoken, magic );
} }
{ {
Magic magic; Magic magic;
auto item = s_queue.enqueue_begin( ptoken, magic ); auto item = s_queue.enqueue_begin( ptoken, magic );
item->hdr.type = QueueType::ZoneEnd; item->hdr.type = QueueType::ZoneEnd;
item->hdr.id = id; item->zoneEnd.thread = 0;
item->zoneEnd.time = GetTime( item->zoneEnd.cpu ); item->zoneEnd.time = GetTime( item->zoneEnd.cpu );
s_queue.enqueue_finish( ptoken, magic ); s_queue.enqueue_finish( ptoken, magic );
} }

View File

@ -33,7 +33,6 @@ struct SourceLocation
extern moodycamel::ConcurrentQueue<QueueItem> s_queue; extern moodycamel::ConcurrentQueue<QueueItem> s_queue;
extern thread_local moodycamel::ProducerToken s_token; extern thread_local moodycamel::ProducerToken s_token;
extern std::atomic<uint64_t> s_id;
using Magic = moodycamel::ConcurrentQueueDefaultTraits::index_t; using Magic = moodycamel::ConcurrentQueueDefaultTraits::index_t;
@ -73,7 +72,6 @@ public:
static tracy_force_inline QueueItem* StartItem( Magic& magic ) { return s_queue.enqueue_begin( s_token, magic ); } static tracy_force_inline QueueItem* StartItem( Magic& magic ) { return s_queue.enqueue_begin( s_token, magic ); }
static tracy_force_inline void FinishItem( Magic magic ) { s_queue.enqueue_finish( s_token, magic ); } static tracy_force_inline void FinishItem( Magic magic ) { s_queue.enqueue_finish( s_token, magic ); }
static tracy_force_inline uint64_t GetNewId() { return s_id.fetch_add( 1, std::memory_order_relaxed ); }
static tracy_force_inline void FrameMark() static tracy_force_inline void FrameMark()
{ {
@ -81,7 +79,7 @@ public:
Magic magic; Magic magic;
auto item = s_queue.enqueue_begin( s_token, magic ); auto item = s_queue.enqueue_begin( s_token, magic );
item->hdr.type = QueueType::FrameMarkMsg; item->hdr.type = QueueType::FrameMarkMsg;
item->hdr.id = (uint64_t)GetTime( cpu ); item->frameMark.time = GetTime( cpu );
s_queue.enqueue_finish( s_token, magic ); s_queue.enqueue_finish( s_token, magic );
} }

View File

@ -14,15 +14,15 @@ class ScopedZone
{ {
public: public:
tracy_force_inline ScopedZone( const SourceLocation* srcloc ) tracy_force_inline ScopedZone( const SourceLocation* srcloc )
: m_id( Profiler::GetNewId() )
{ {
const auto thread = GetThreadHandle();
m_thread = thread;
Magic magic; Magic magic;
auto item = Profiler::StartItem( magic ); auto item = Profiler::StartItem( magic );
item->hdr.type = QueueType::ZoneBegin; item->hdr.type = QueueType::ZoneBegin;
item->hdr.id = m_id;
item->zoneBegin.time = Profiler::GetTime( item->zoneBegin.cpu ); item->zoneBegin.time = Profiler::GetTime( item->zoneBegin.cpu );
item->zoneBegin.thread = thread;
item->zoneBegin.srcloc = (uint64_t)srcloc; item->zoneBegin.srcloc = (uint64_t)srcloc;
item->zoneBegin.thread = GetThreadHandle();
Profiler::FinishItem( magic ); Profiler::FinishItem( magic );
} }
@ -31,8 +31,8 @@ public:
Magic magic; Magic magic;
auto item = Profiler::StartItem( magic ); auto item = Profiler::StartItem( magic );
item->hdr.type = QueueType::ZoneEnd; item->hdr.type = QueueType::ZoneEnd;
item->hdr.id = m_id;
item->zoneEnd.time = Profiler::GetTime( item->zoneEnd.cpu ); item->zoneEnd.time = Profiler::GetTime( item->zoneEnd.cpu );
item->zoneEnd.thread = m_thread;
Profiler::FinishItem( magic ); Profiler::FinishItem( magic );
} }
@ -44,7 +44,7 @@ public:
ptr[size] = '\0'; ptr[size] = '\0';
auto item = Profiler::StartItem( magic ); auto item = Profiler::StartItem( magic );
item->hdr.type = QueueType::ZoneText; item->hdr.type = QueueType::ZoneText;
item->hdr.id = m_id; item->zoneText.thread = m_thread;
item->zoneText.text = (uint64_t)ptr; item->zoneText.text = (uint64_t)ptr;
Profiler::FinishItem( magic ); Profiler::FinishItem( magic );
} }
@ -54,13 +54,13 @@ public:
Magic magic; Magic magic;
auto item = Profiler::StartItem( magic ); auto item = Profiler::StartItem( magic );
item->hdr.type = QueueType::ZoneName; item->hdr.type = QueueType::ZoneName;
item->hdr.id = m_id; item->zoneName.thread = m_thread;
item->zoneName.name = (uint64_t)name; item->zoneName.name = (uint64_t)name;
Profiler::FinishItem( magic ); Profiler::FinishItem( magic );
} }
private: private:
uint64_t m_id; uint64_t m_thread;
}; };
} }

View File

@ -25,19 +25,31 @@ enum class QueueType : uint8_t
struct QueueZoneBegin struct QueueZoneBegin
{ {
int64_t time; int64_t time;
uint64_t srcloc; // ptr
uint64_t thread; uint64_t thread;
uint64_t srcloc; // ptr
int8_t cpu; int8_t cpu;
}; };
struct QueueZoneEnd struct QueueZoneEnd
{ {
int64_t time; int64_t time;
uint64_t thread;
int8_t cpu; int8_t cpu;
}; };
struct QueueStringTransfer
{
uint64_t ptr;
};
struct QueueFrameMark
{
int64_t time;
};
struct QueueSourceLocation struct QueueSourceLocation
{ {
uint64_t ptr;
uint64_t function; // ptr uint64_t function; // ptr
uint64_t file; // ptr uint64_t file; // ptr
uint32_t line; uint32_t line;
@ -46,11 +58,13 @@ struct QueueSourceLocation
struct QueueZoneText struct QueueZoneText
{ {
uint64_t thread;
uint64_t text; // ptr uint64_t text; // ptr
}; };
struct QueueZoneName struct QueueZoneName
{ {
uint64_t thread;
uint64_t name; // ptr uint64_t name; // ptr
}; };
@ -61,7 +75,6 @@ struct QueueHeader
QueueType type; QueueType type;
uint8_t idx; uint8_t idx;
}; };
uint64_t id;
}; };
struct QueueItem struct QueueItem
@ -71,6 +84,8 @@ struct QueueItem
{ {
QueueZoneBegin zoneBegin; QueueZoneBegin zoneBegin;
QueueZoneEnd zoneEnd; QueueZoneEnd zoneEnd;
QueueStringTransfer stringTransfer;
QueueFrameMark frameMark;
QueueSourceLocation srcloc; QueueSourceLocation srcloc;
QueueZoneText zoneText; QueueZoneText zoneText;
QueueZoneName zoneName; QueueZoneName zoneName;
@ -84,10 +99,10 @@ enum { QueueItemSize = sizeof( QueueItem ) };
static const size_t QueueDataSize[] = { static const size_t QueueDataSize[] = {
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), sizeof( QueueHeader ) + sizeof( QueueZoneBegin ),
sizeof( QueueHeader ) + sizeof( QueueZoneEnd ), sizeof( QueueHeader ) + sizeof( QueueZoneEnd ),
sizeof( QueueHeader ), // string data sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data
sizeof( QueueHeader ), // thread name sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name
sizeof( QueueHeader ), // custom string data sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // custom string data
sizeof( QueueHeader ), // frame mark sizeof( QueueHeader ) + sizeof( QueueFrameMark ),
sizeof( QueueHeader ) + sizeof( QueueSourceLocation ), sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),
sizeof( QueueHeader ) + sizeof( QueueZoneText ), sizeof( QueueHeader ) + sizeof( QueueZoneText ),
sizeof( QueueHeader ) + sizeof( QueueZoneName ), sizeof( QueueHeader ) + sizeof( QueueZoneName ),

View File

@ -280,15 +280,15 @@ void View::DispatchProcess( const QueueItem& ev )
m_sock.Read( buf, sz, &tv, ShouldExit ); m_sock.Read( buf, sz, &tv, ShouldExit );
if( ev.hdr.type == QueueType::CustomStringData ) if( ev.hdr.type == QueueType::CustomStringData )
{ {
AddCustomString( ev.hdr.id, std::string( buf, buf+sz ) ); AddCustomString( ev.stringTransfer.ptr, std::string( buf, buf+sz ) );
} }
else if( ev.hdr.type == QueueType::StringData ) else if( ev.hdr.type == QueueType::StringData )
{ {
AddString( ev.hdr.id, std::string( buf, buf+sz ) ); AddString( ev.stringTransfer.ptr, std::string( buf, buf+sz ) );
} }
else else
{ {
AddThreadString( ev.hdr.id, std::string( buf, buf+sz ) ); AddThreadString( ev.stringTransfer.ptr, std::string( buf, buf+sz ) );
} }
} }
else else
@ -307,15 +307,15 @@ void View::DispatchProcess( const QueueItem& ev, const char*& ptr )
ptr += sizeof( sz ); ptr += sizeof( sz );
if( ev.hdr.type == QueueType::CustomStringData ) if( ev.hdr.type == QueueType::CustomStringData )
{ {
AddCustomString( ev.hdr.id, std::string( ptr, ptr+sz ) ); AddCustomString( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) );
} }
else if( ev.hdr.type == QueueType::StringData ) else if( ev.hdr.type == QueueType::StringData )
{ {
AddString( ev.hdr.id, std::string( ptr, ptr+sz ) ); AddString( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) );
} }
else else
{ {
AddThreadString( ev.hdr.id, std::string( ptr, ptr+sz ) ); AddThreadString( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) );
} }
ptr += sz; ptr += sz;
} }
@ -339,22 +339,22 @@ void View::Process( const QueueItem& ev )
switch( ev.hdr.type ) switch( ev.hdr.type )
{ {
case QueueType::ZoneBegin: case QueueType::ZoneBegin:
ProcessZoneBegin( ev.hdr.id, ev.zoneBegin ); ProcessZoneBegin( ev.zoneBegin );
break; break;
case QueueType::ZoneEnd: case QueueType::ZoneEnd:
ProcessZoneEnd( ev.hdr.id, ev.zoneEnd ); ProcessZoneEnd( ev.zoneEnd );
break; break;
case QueueType::FrameMarkMsg: case QueueType::FrameMarkMsg:
ProcessFrameMark( ev.hdr.id ); ProcessFrameMark( ev.frameMark );
break; break;
case QueueType::SourceLocation: case QueueType::SourceLocation:
AddSourceLocation( ev.hdr.id, ev.srcloc ); AddSourceLocation( ev.srcloc );
break; break;
case QueueType::ZoneText: case QueueType::ZoneText:
ProcessZoneText( ev.hdr.id, ev.zoneText ); ProcessZoneText( ev.zoneText );
break; break;
case QueueType::ZoneName: case QueueType::ZoneName:
ProcessZoneName( ev.hdr.id, ev.zoneName ); ProcessZoneName( ev.zoneName );
break; break;
default: default:
assert( false ); assert( false );
@ -362,7 +362,7 @@ void View::Process( const QueueItem& ev )
} }
} }
void View::ProcessZoneBegin( uint64_t id, const QueueZoneBegin& ev ) void View::ProcessZoneBegin( const QueueZoneBegin& ev )
{ {
auto zone = m_slab.Alloc<Event>(); auto zone = m_slab.Alloc<Event>();
@ -378,47 +378,49 @@ void View::ProcessZoneBegin( uint64_t id, const QueueZoneBegin& ev )
std::unique_lock<std::mutex> lock( m_lock ); std::unique_lock<std::mutex> lock( m_lock );
NewZone( zone, ev.thread ); NewZone( zone, ev.thread );
lock.unlock(); lock.unlock();
m_openZones.emplace( id, zone ); m_zoneStack[ev.thread].push_back( zone );
} }
void View::ProcessZoneEnd( uint64_t id, const QueueZoneEnd& ev ) void View::ProcessZoneEnd( const QueueZoneEnd& ev )
{ {
auto it = m_openZones.find( id ); auto& stack = m_zoneStack[ev.thread];
assert( it != m_openZones.end() ); assert( !stack.empty() );
auto zone = it->second; auto zone = stack.back();
std::unique_lock<std::mutex> lock( m_lock ); stack.pop_back();
assert( zone->end == -1 ); assert( zone->end == -1 );
std::unique_lock<std::mutex> lock( m_lock );
zone->end = ev.time * m_timerMul; zone->end = ev.time * m_timerMul;
zone->cpu_end = ev.cpu; zone->cpu_end = ev.cpu;
lock.unlock();
assert( zone->end >= zone->start ); assert( zone->end >= zone->start );
UpdateZone( zone ); UpdateZone( zone );
lock.unlock();
m_openZones.erase( it );
} }
void View::ProcessFrameMark( uint64_t id ) void View::ProcessFrameMark( const QueueFrameMark& ev )
{ {
assert( !m_frames.empty() ); assert( !m_frames.empty() );
const auto lastframe = m_frames.back(); const auto lastframe = m_frames.back();
const auto time = id * m_timerMul; const auto time = ev.time * m_timerMul;
assert( lastframe < time ); assert( lastframe < time );
std::unique_lock<std::mutex> lock( m_lock ); std::unique_lock<std::mutex> lock( m_lock );
m_frames.push_back( time ); m_frames.push_back( time );
} }
void View::ProcessZoneText( uint64_t id, const QueueZoneText& ev ) void View::ProcessZoneText( const QueueZoneText& ev )
{ {
auto it = m_openZones.find( id ); auto& stack = m_zoneStack[ev.thread];
assert( it != m_openZones.end() ); assert( !stack.empty() );
CheckCustomString( ev.text, it->second ); auto zone = stack.back();
CheckCustomString( ev.text, zone );
} }
void View::ProcessZoneName( uint64_t id, const QueueZoneName& ev ) void View::ProcessZoneName( const QueueZoneName& ev )
{ {
auto it = m_openZones.find( id ); auto& stack = m_zoneStack[ev.thread];
assert( it != m_openZones.end() ); assert( !stack.empty() );
auto zone = stack.back();
CheckString( ev.name ); CheckString( ev.name );
GetTextData( *it->second )->zoneName = ev.name; GetTextData( *zone )->zoneName = ev.name;
} }
void View::CheckString( uint64_t ptr ) void View::CheckString( uint64_t ptr )
@ -500,16 +502,16 @@ void View::AddCustomString( uint64_t ptr, std::string&& str )
m_pendingCustomStrings.erase( pit ); m_pendingCustomStrings.erase( pit );
} }
void View::AddSourceLocation( uint64_t ptr, const QueueSourceLocation& srcloc ) void View::AddSourceLocation( const QueueSourceLocation& srcloc )
{ {
assert( m_sourceLocation.find( ptr ) == m_sourceLocation.end() ); assert( m_sourceLocation.find( srcloc.ptr ) == m_sourceLocation.end() );
auto it = m_pendingSourceLocation.find( ptr ); auto it = m_pendingSourceLocation.find( srcloc.ptr );
assert( it != m_pendingSourceLocation.end() ); assert( it != m_pendingSourceLocation.end() );
m_pendingSourceLocation.erase( it ); m_pendingSourceLocation.erase( it );
CheckString( srcloc.file ); CheckString( srcloc.file );
CheckString( srcloc.function ); CheckString( srcloc.function );
std::lock_guard<std::mutex> lock( m_lock ); std::lock_guard<std::mutex> lock( m_lock );
m_sourceLocation.emplace( ptr, srcloc ); m_sourceLocation.emplace( srcloc.ptr, srcloc );
} }
void View::NewZone( Event* zone, uint64_t thread ) void View::NewZone( Event* zone, uint64_t thread )

View File

@ -52,11 +52,11 @@ private:
void ServerQuery( uint8_t type, uint64_t data ); void ServerQuery( uint8_t type, uint64_t data );
void Process( const QueueItem& ev ); void Process( const QueueItem& ev );
void ProcessZoneBegin( uint64_t id, const QueueZoneBegin& ev ); void ProcessZoneBegin( const QueueZoneBegin& ev );
void ProcessZoneEnd( uint64_t id, const QueueZoneEnd& ev ); void ProcessZoneEnd( const QueueZoneEnd& ev );
void ProcessFrameMark( uint64_t id ); void ProcessFrameMark( const QueueFrameMark& ev );
void ProcessZoneText( uint64_t id, const QueueZoneText& ev ); void ProcessZoneText( const QueueZoneText& ev );
void ProcessZoneName( uint64_t id, const QueueZoneName& ev ); void ProcessZoneName( const QueueZoneName& ev );
void CheckString( uint64_t ptr ); void CheckString( uint64_t ptr );
void CheckThreadString( uint64_t id ); void CheckThreadString( uint64_t id );
@ -66,7 +66,7 @@ private:
void AddString( uint64_t ptr, std::string&& str ); void AddString( uint64_t ptr, std::string&& str );
void AddThreadString( uint64_t id, std::string&& str ); void AddThreadString( uint64_t id, std::string&& str );
void AddCustomString( uint64_t ptr, std::string&& str ); void AddCustomString( uint64_t ptr, std::string&& str );
void AddSourceLocation( uint64_t id, const QueueSourceLocation& srcloc ); void AddSourceLocation( const QueueSourceLocation& srcloc );
void NewZone( Event* zone, uint64_t thread ); void NewZone( Event* zone, uint64_t thread );
void UpdateZone( Event* zone ); void UpdateZone( Event* zone );
@ -126,7 +126,7 @@ private:
std::vector<float> m_mbps; std::vector<float> m_mbps;
// not used for vis - no need to lock // not used for vis - no need to lock
std::unordered_map<uint64_t, Event*> m_openZones; std::unordered_map<uint64_t, std::vector<Event*>> m_zoneStack;
std::unordered_set<uint64_t> m_pendingStrings; std::unordered_set<uint64_t> m_pendingStrings;
std::unordered_set<uint64_t> m_pendingThreads; std::unordered_set<uint64_t> m_pendingThreads;
std::unordered_set<uint64_t> m_pendingSourceLocation; std::unordered_set<uint64_t> m_pendingSourceLocation;