From d6f32a0839234c757c3128a9e3a7669a5e189467 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 12 Aug 2019 13:51:01 +0200 Subject: [PATCH] Serialize lock processing. This makes is much easier to process on the server and opens new optimization possibilities. It also fixes theoretical problems, which may be caused by invalid ordering of events with the same timestamp. --- client/TracyLock.hpp | 118 ++++++++++++++++----------------------- common/TracyProtocol.hpp | 2 +- common/TracyQueue.hpp | 4 ++ server/TracyWorker.cpp | 25 ++++----- 4 files changed, 63 insertions(+), 86 deletions(-) diff --git a/client/TracyLock.hpp b/client/TracyLock.hpp index eef7d23f..5292c41f 100644 --- a/client/TracyLock.hpp +++ b/client/TracyLock.hpp @@ -80,29 +80,27 @@ public: return; } #endif + const auto thread = GetThreadHandle(); + { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockWait ); + MemWrite( &item->lockWait.thread, thread ); MemWrite( &item->lockWait.id, m_id ); MemWrite( &item->lockWait.time, Profiler::GetTime() ); MemWrite( &item->lockWait.type, LockType::Lockable ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } m_lockable.lock(); { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, thread ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } } @@ -120,14 +118,12 @@ public: } #endif - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockRelease ); + MemWrite( &item->lockRelease.thread, GetThreadHandle() ); MemWrite( &item->lockRelease.id, m_id ); MemWrite( &item->lockRelease.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } tracy_force_inline bool try_lock() @@ -151,14 +147,12 @@ public: if( ret ) { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } return ret; @@ -177,14 +171,12 @@ public: } #endif - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockMark ); + MemWrite( &item->lockMark.thread, GetThreadHandle() ); MemWrite( &item->lockMark.id, m_id ); MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } private: @@ -267,29 +259,27 @@ public: return; } #endif + const auto thread = GetThreadHandle(); + { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockWait ); + MemWrite( &item->lockWait.thread, thread ); MemWrite( &item->lockWait.id, m_id ); MemWrite( &item->lockWait.time, Profiler::GetTime() ); MemWrite( &item->lockWait.type, LockType::SharedLockable ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } m_lockable.lock(); { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, thread ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } } @@ -307,14 +297,12 @@ public: } #endif - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockRelease ); + MemWrite( &item->lockRelease.thread, GetThreadHandle() ); MemWrite( &item->lockRelease.id, m_id ); MemWrite( &item->lockRelease.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } tracy_force_inline bool try_lock() @@ -338,14 +326,12 @@ public: if( ret ) { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } return ret; @@ -369,29 +355,27 @@ public: return; } #endif + const auto thread = GetThreadHandle(); + { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockSharedWait ); + MemWrite( &item->lockWait.thread, thread ); MemWrite( &item->lockWait.id, m_id ); MemWrite( &item->lockWait.time, Profiler::GetTime() ); MemWrite( &item->lockWait.type, LockType::SharedLockable ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } m_lockable.lock_shared(); { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockSharedObtain ); + MemWrite( &item->lockObtain.thread, thread ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } } @@ -409,14 +393,12 @@ public: } #endif - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockSharedRelease ); + MemWrite( &item->lockRelease.thread, GetThreadHandle() ); MemWrite( &item->lockRelease.id, m_id ); MemWrite( &item->lockRelease.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } tracy_force_inline bool try_lock_shared() @@ -440,14 +422,12 @@ public: if( ret ) { - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockSharedObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); MemWrite( &item->lockObtain.id, m_id ); MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } return ret; @@ -466,14 +446,12 @@ public: } #endif - Magic magic; - auto token = GetToken(); - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockMark ); + MemWrite( &item->lockMark.thread, GetThreadHandle() ); MemWrite( &item->lockMark.id, m_id ); MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc ); - tail.store( magic + 1, std::memory_order_release ); + Profiler::QueueSerialFinish(); } private: diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index 652f5cc9..9ffc61ac 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -9,7 +9,7 @@ namespace tracy { -enum : uint32_t { ProtocolVersion = 14 }; +enum : uint32_t { ProtocolVersion = 15 }; enum : uint32_t { BroadcastVersion = 0 }; using lz4sz_t = uint32_t; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 8f4cb4f5..e91755fd 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -152,6 +152,7 @@ struct QueueLockTerminate struct QueueLockWait { + uint64_t thread; uint32_t id; int64_t time; LockType type; @@ -159,18 +160,21 @@ struct QueueLockWait struct QueueLockObtain { + uint64_t thread; uint32_t id; int64_t time; }; struct QueueLockRelease { + uint64_t thread; uint32_t id; int64_t time; }; struct QueueLockMark { + uint64_t thread; uint32_t id; uint64_t srcloc; // ptr }; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 498f43c4..03958f66 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -2064,16 +2064,11 @@ void Worker::InsertLockEvent( LockMap& lockmap, LockEvent* lev, uint64_t thread timeline.push_back( { lev } ); UpdateLockCount( lockmap, timeline.size() - 1 ); } - else if( timeline.back().ptr->time <= lt ) - { - timeline.push_back_non_empty( { lev } ); - UpdateLockCount( lockmap, timeline.size() - 1 ); - } else { - auto it = std::upper_bound( timeline.begin(), timeline.end(), lt, [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.ptr->time; } ); - it = timeline.insert( it, { lev } ); - UpdateLockCount( lockmap, std::distance( timeline.begin(), it ) ); + assert( timeline.back().ptr->time <= lt ); + timeline.push_back_non_empty( { lev } ); + UpdateLockCount( lockmap, timeline.size() - 1 ); } auto& range = lockmap.range[it->second]; @@ -3040,7 +3035,7 @@ void Worker::ProcessLockWait( const QueueLockWait& ev ) lev->type = LockEvent::Type::Wait; lev->srcloc = 0; - InsertLockEvent( *it->second, lev, m_threadCtx ); + InsertLockEvent( *it->second, lev, ev.thread ); } void Worker::ProcessLockObtain( const QueueLockObtain& ev ) @@ -3054,7 +3049,7 @@ void Worker::ProcessLockObtain( const QueueLockObtain& ev ) lev->type = LockEvent::Type::Obtain; lev->srcloc = 0; - InsertLockEvent( lock, lev, m_threadCtx ); + InsertLockEvent( lock, lev, ev.thread ); } void Worker::ProcessLockRelease( const QueueLockRelease& ev ) @@ -3068,7 +3063,7 @@ void Worker::ProcessLockRelease( const QueueLockRelease& ev ) lev->type = LockEvent::Type::Release; lev->srcloc = 0; - InsertLockEvent( lock, lev, m_threadCtx ); + InsertLockEvent( lock, lev, ev.thread ); } void Worker::ProcessLockSharedWait( const QueueLockWait& ev ) @@ -3089,7 +3084,7 @@ void Worker::ProcessLockSharedWait( const QueueLockWait& ev ) lev->type = LockEvent::Type::WaitShared; lev->srcloc = 0; - InsertLockEvent( *it->second, lev, m_threadCtx ); + InsertLockEvent( *it->second, lev, ev.thread ); } void Worker::ProcessLockSharedObtain( const QueueLockObtain& ev ) @@ -3104,7 +3099,7 @@ void Worker::ProcessLockSharedObtain( const QueueLockObtain& ev ) lev->type = LockEvent::Type::ObtainShared; lev->srcloc = 0; - InsertLockEvent( lock, lev, m_threadCtx ); + InsertLockEvent( lock, lev, ev.thread ); } void Worker::ProcessLockSharedRelease( const QueueLockRelease& ev ) @@ -3119,7 +3114,7 @@ void Worker::ProcessLockSharedRelease( const QueueLockRelease& ev ) lev->type = LockEvent::Type::ReleaseShared; lev->srcloc = 0; - InsertLockEvent( lock, lev, m_threadCtx ); + InsertLockEvent( lock, lev, ev.thread ); } void Worker::ProcessLockMark( const QueueLockMark& ev ) @@ -3128,7 +3123,7 @@ void Worker::ProcessLockMark( const QueueLockMark& ev ) auto lit = m_data.lockMap.find( ev.id ); assert( lit != m_data.lockMap.end() ); auto& lockmap = *lit->second; - auto tid = lockmap.threadMap.find( m_threadCtx ); + auto tid = lockmap.threadMap.find( ev.thread ); assert( tid != lockmap.threadMap.end() ); const auto thread = tid->second; auto it = lockmap.timeline.end();