From 991fc6bd95baffa3f1a49e5a3ff78c69a43fad8c Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 31 Mar 2018 21:56:05 +0200 Subject: [PATCH 01/58] Memory allocations tracker. --- Tracy.hpp | 3 +++ client/TracyProfiler.hpp | 27 +++++++++++++++++++++++++++ common/TracyQueue.hpp | 21 +++++++++++++++++++++ server/TracyWorker.cpp | 4 ++++ 4 files changed, 55 insertions(+) diff --git a/Tracy.hpp b/Tracy.hpp index d8ed519b..bfc1e81c 100644 --- a/Tracy.hpp +++ b/Tracy.hpp @@ -57,6 +57,9 @@ #define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size ); #define TracyMessageL( txt ) tracy::Profiler::Message( txt ); +#define TracyAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size ); +#define TracyFree( ptr ) tracy::Profiler::MemFree( ptr ); + #endif #endif diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 1666d0c9..ea3af51c 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -186,6 +186,33 @@ public: tail.store( magic + 1, std::memory_order_release ); } + static tracy_force_inline void MemAlloc( const void* ptr, size_t size ) + { + Magic magic; + auto& token = s_token.ptr; + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::MemAlloc ); + MemWrite( &item->memAlloc.time, GetTime() ); + MemWrite( &item->memAlloc.thread, GetThreadHandle() ); + MemWrite( &item->memAlloc.ptr, (uint64_t)ptr ); + memcpy( &item->memAlloc.size, &size, 6 ); + tail.store( magic + 1, std::memory_order_release ); + } + + static tracy_force_inline void MemFree( const void* ptr ) + { + Magic magic; + auto& token = s_token.ptr; + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::MemFree ); + MemWrite( &item->memFree.time, GetTime() ); + MemWrite( &item->memFree.thread, GetThreadHandle() ); + MemWrite( &item->memFree.ptr, (uint64_t)ptr ); + tail.store( magic + 1, std::memory_order_release ); + } + static bool ShouldExit(); private: diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 0762f39c..69c0f6b6 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -31,6 +31,8 @@ enum class QueueType : uint8_t GpuZoneEnd, GpuTime, GpuResync, + MemAlloc, + MemFree, StringData, ThreadName, CustomStringData, @@ -187,6 +189,21 @@ struct QueueGpuResync uint16_t context; }; +struct QueueMemAlloc +{ + int64_t time; + uint64_t thread; + uint64_t ptr; + char size[6]; +}; + +struct QueueMemFree +{ + int64_t time; + uint64_t thread; + uint64_t ptr; +}; + struct QueueHeader { union @@ -219,6 +236,8 @@ struct QueueItem QueueGpuZoneEnd gpuZoneEnd; QueueGpuTime gpuTime; QueueGpuResync gpuResync; + QueueMemAlloc memAlloc; + QueueMemFree memFree; }; }; @@ -251,6 +270,8 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ), sizeof( QueueHeader ) + sizeof( QueueGpuTime ), sizeof( QueueHeader ) + sizeof( QueueGpuResync ), + sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), + sizeof( QueueHeader ) + sizeof( QueueMemFree ), // keep all QueueStringTransfer below sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 43463b1d..8f090755 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1200,6 +1200,10 @@ void Worker::Process( const QueueItem& ev ) case QueueType::GpuResync: ProcessGpuResync( ev.gpuResync ); break; + case QueueType::MemAlloc: + break; + case QueueType::MemFree: + break; case QueueType::Terminate: m_terminate = true; break; From b12375815caa70ee299168903af7b847263d9c96 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 02:03:34 +0200 Subject: [PATCH 02/58] Broken memory events processing. --- server/TracyEvent.hpp | 25 +++++++++++ server/TracyWorker.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++ server/TracyWorker.hpp | 5 +++ 3 files changed, 124 insertions(+) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 463bd1ff..53eef83c 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -137,6 +137,20 @@ struct GpuEvent enum { GpuEventSize = sizeof( GpuEvent ) }; static_assert( std::is_standard_layout::value, "GpuEvent is not standard layout" ); + +struct MemEvent +{ + uint64_t ptr; + uint64_t size; + int64_t timeAlloc; + uint16_t threadAlloc; + int64_t timeFree; + uint16_t threadFree; +}; + +enum { MemEventSize = sizeof( MemEvent ) }; +static_assert( std::is_standard_layout::value, "MemEvent is not standard layout" ); + #pragma pack() @@ -208,6 +222,17 @@ struct PlotData uint64_t postponeTime; }; +struct MemData +{ + Vector data; + Vector postpone; + uint64_t postponeTime; + flat_hash_map> active; + flat_hash_map> zombie; + uint64_t high = std::numeric_limits::min(); + uint64_t low = std::numeric_limits::max(); +}; + struct StringLocation { const char* ptr; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 8f090755..42b20a09 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -525,6 +525,7 @@ void Worker::Exec() if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0; HandlePostponedPlots(); + HandlePostponedMemory(); } auto t1 = std::chrono::high_resolution_clock::now(); @@ -1201,8 +1202,10 @@ void Worker::Process( const QueueItem& ev ) ProcessGpuResync( ev.gpuResync ); break; case QueueType::MemAlloc: + ProcessMemAlloc( ev.memAlloc ); break; case QueueType::MemFree: + ProcessMemFree( ev.memFree ); break; case QueueType::Terminate: m_terminate = true; @@ -1629,6 +1632,97 @@ void Worker::ProcessGpuResync( const QueueGpuResync& ev ) } } +void Worker::ProcessMemAlloc( const QueueMemAlloc& ev ) +{ + MemEvent* mem; + const auto time = TscTime( ev.time ); + + auto it = m_data.memory.zombie.find( ev.ptr ); + if( it == m_data.memory.zombie.end() ) + { + mem = m_slab.Alloc(); + mem->ptr = ev.ptr; + mem->timeFree = -1; + mem->threadFree = 0; + } + else + { + mem = it->second; + m_data.memory.zombie.erase( it ); + } + + mem->size = 0; + memcpy( &mem->size, ev.size, 6 ); + mem->timeAlloc = time; + mem->threadAlloc = CompressThread( ev.thread ); + + m_data.memory.low = std::min( m_data.memory.low, mem->ptr ); + m_data.memory.high = std::max( m_data.memory.high, mem->ptr + mem->size ); + + assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); // this assert is not valid; memory may have been freed, but the information has not yet arrived + m_data.memory.active.emplace( ev.ptr, mem ); + + if( m_data.memory.data.empty() ) + { + m_data.memory.data.push_back( mem ); + } + else if( m_data.memory.data.back()->timeAlloc < time ) + { + m_data.memory.data.push_back_non_empty( mem ); + } + else + { + if( m_data.memory.postpone.empty() ) + { + m_data.memory.postponeTime = std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); + m_data.memory.postpone.push_back( mem ); + } + else + { + m_data.memory.postpone.push_back_non_empty( mem ); + } + } +} + +void Worker::ProcessMemFree( const QueueMemFree& ev ) +{ + MemEvent* mem; + + auto it = m_data.memory.active.find( ev.ptr ); + if( it == m_data.memory.active.end() ) + { + mem = m_slab.Alloc(); + mem->ptr = ev.ptr; + + assert( m_data.memory.zombie.find( ev.ptr ) == m_data.memory.zombie.end() ); // this assert is not valid; there may be multiple alloc+frees queued for the same address + m_data.memory.zombie.emplace( ev.ptr, mem ); + } + else + { + mem = it->second; + m_data.memory.active.erase( it ); + } + + mem->timeFree = TscTime( ev.time ); + mem->threadFree = CompressThread( ev.thread ); +} + +void Worker::HandlePostponedMemory() +{ + auto& src = m_data.memory.postpone; + if( src.empty() ) return; + if( std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count() - m_data.memory.postponeTime < 100 ) return; + auto& dst = m_data.memory.data; + std::sort( src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l->timeAlloc < r->timeAlloc; } ); + const auto ds = std::lower_bound( dst.begin(), dst.end(), src.front()->timeAlloc, [] ( const auto& l, const auto& r ) { return l->timeAlloc < r; } ); + const auto dsd = std::distance( dst.begin(), ds ) ; + const auto de = std::lower_bound( ds, dst.end(), src.back()->timeAlloc, [] ( const auto& l, const auto& r ) { return l->timeAlloc < 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->timeAlloc < r->timeAlloc; } ); + src.clear(); +} + void Worker::ReadTimeline( FileRead& f, Vector& vec, uint16_t thread ) { uint64_t sz; diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 748181de..6ff1c3bc 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -57,6 +57,7 @@ class Worker Vector messages; Vector plots; Vector threads; + MemData memory; uint64_t zonesCnt; int64_t lastTime; @@ -177,6 +178,8 @@ private: tracy_force_inline void ProcessGpuZoneEnd( const QueueGpuZoneEnd& ev ); tracy_force_inline void ProcessGpuTime( const QueueGpuTime& ev ); tracy_force_inline void ProcessGpuResync( const QueueGpuResync& ev ); + tracy_force_inline void ProcessMemAlloc( const QueueMemAlloc& ev ); + tracy_force_inline void ProcessMemFree( const QueueMemFree& ev ); tracy_force_inline void CheckSourceLocation( uint64_t ptr ); void NewSourceLocation( uint64_t ptr ); @@ -204,7 +207,9 @@ private: void InsertPlot( PlotData* plot, int64_t time, double val ); void HandlePlotName( uint64_t name, char* str, size_t sz ); + void HandlePostponedPlots(); + void HandlePostponedMemory(); StringLocation StoreString( char* str, size_t sz ); uint16_t CompressThreadNew( uint64_t thread ); From 16a98c8c1770d385b4ec2eb42ad11d4d0d5e38ee Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 18:59:55 +0200 Subject: [PATCH 03/58] Move benaphore to common directory. --- capture/build/win32/capture.vcxproj | 4 ++-- capture/build/win32/capture.vcxproj.filters | 12 ++++++------ capture/src/capture.cpp | 1 - {server => common}/tracy_benaphore.h | 0 {server => common}/tracy_sema.h | 0 server/TracyView.hpp | 2 +- server/TracyWorker.hpp | 2 +- standalone/build/win32/Tracy.vcxproj | 4 ++-- standalone/build/win32/Tracy.vcxproj.filters | 12 ++++++------ 9 files changed, 18 insertions(+), 19 deletions(-) rename {server => common}/tracy_benaphore.h (100%) rename {server => common}/tracy_sema.h (100%) diff --git a/capture/build/win32/capture.vcxproj b/capture/build/win32/capture.vcxproj index 23761818..aef83464 100644 --- a/capture/build/win32/capture.vcxproj +++ b/capture/build/win32/capture.vcxproj @@ -144,7 +144,9 @@ + + @@ -153,9 +155,7 @@ - - diff --git a/capture/build/win32/capture.vcxproj.filters b/capture/build/win32/capture.vcxproj.filters index e9183070..01444809 100644 --- a/capture/build/win32/capture.vcxproj.filters +++ b/capture/build/win32/capture.vcxproj.filters @@ -59,15 +59,9 @@ common - - server - server - - server - server @@ -98,5 +92,11 @@ common + + common + + + common + \ No newline at end of file diff --git a/capture/src/capture.cpp b/capture/src/capture.cpp index 17e673ad..46dff6ca 100644 --- a/capture/src/capture.cpp +++ b/capture/src/capture.cpp @@ -9,7 +9,6 @@ #include #include -#include "../../server/tracy_benaphore.h" #include "../../server/TracyFileWrite.hpp" #include "../../server/TracyMemory.hpp" #include "../../server/TracyWorker.hpp" diff --git a/server/tracy_benaphore.h b/common/tracy_benaphore.h similarity index 100% rename from server/tracy_benaphore.h rename to common/tracy_benaphore.h diff --git a/server/tracy_sema.h b/common/tracy_sema.h similarity index 100% rename from server/tracy_sema.h rename to common/tracy_sema.h diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 6b930e32..0c3a74c2 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -7,9 +7,9 @@ #include #include +#include "../common/tracy_benaphore.h" #include "TracyVector.hpp" #include "TracyWorker.hpp" -#include "tracy_benaphore.h" #include "tracy_flat_hash_map.hpp" struct ImVec2; diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 6ff1c3bc..9c0cae1a 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -8,11 +8,11 @@ #include #include +#include "../common/tracy_benaphore.h" #include "../common/tracy_lz4.hpp" #include "../common/TracyForceInline.hpp" #include "../common/TracyQueue.hpp" #include "../common/TracySocket.hpp" -#include "tracy_benaphore.h" #include "tracy_flat_hash_map.hpp" #include "TracyEvent.hpp" #include "TracySlab.hpp" diff --git a/standalone/build/win32/Tracy.vcxproj b/standalone/build/win32/Tracy.vcxproj index 50e15091..9b5101fc 100644 --- a/standalone/build/win32/Tracy.vcxproj +++ b/standalone/build/win32/Tracy.vcxproj @@ -103,7 +103,9 @@ + + @@ -124,10 +126,8 @@ - - diff --git a/standalone/build/win32/Tracy.vcxproj.filters b/standalone/build/win32/Tracy.vcxproj.filters index 0fdd0304..fe6814c7 100644 --- a/standalone/build/win32/Tracy.vcxproj.filters +++ b/standalone/build/win32/Tracy.vcxproj.filters @@ -146,12 +146,6 @@ server - - server - - - server - server @@ -167,6 +161,12 @@ common + + imgui + + + imgui + From 66ad415ce5b59b7ca62d1b330322d133b6afc963 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 19:15:46 +0200 Subject: [PATCH 04/58] Remove windows.h dependency from tracy_sema.h. --- common/tracy_sema.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/common/tracy_sema.h b/common/tracy_sema.h index da3f088a..0b76e10c 100644 --- a/common/tracy_sema.h +++ b/common/tracy_sema.h @@ -30,9 +30,16 @@ namespace tracy // Semaphore (Windows) //--------------------------------------------------------- -#include -#undef min -#undef max +#ifndef MAXLONG +enum { MAXLONG = 0x7fffffff }; +enum { INFINITE = 0xFFFFFFFF }; +typedef void* HANDLE; + +extern "C" __declspec(dllimport) HANDLE __stdcall CreateSemaphoreA( void*, long, long, const char* ); +extern "C" __declspec(dllimport) int __stdcall CloseHandle( HANDLE ); +extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject( HANDLE, unsigned long ); +extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore( HANDLE, long, long* ); +#endif class Semaphore { @@ -46,7 +53,7 @@ public: Semaphore(int initialCount = 0) { assert(initialCount >= 0); - m_hSema = CreateSemaphore(NULL, initialCount, MAXLONG, NULL); + m_hSema = CreateSemaphoreA(NULL, initialCount, MAXLONG, NULL); } ~Semaphore() From 0a3e9f85ebe0ab1e6ecd8ebc31887d517ef4b85f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 19:52:29 +0200 Subject: [PATCH 05/58] "Fast" vector implementation. --- client/TracyFastVector.hpp | 88 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 client/TracyFastVector.hpp diff --git a/client/TracyFastVector.hpp b/client/TracyFastVector.hpp new file mode 100644 index 00000000..f0757dfe --- /dev/null +++ b/client/TracyFastVector.hpp @@ -0,0 +1,88 @@ +#ifndef __TRACYFASTVECTOR_HPP__ +#define __TRACYFASTVECTOR_HPP__ + +#include + +#include "../common/TracyAlloc.hpp" +#include "../common/TracyForceInline.hpp" + +namespace tracy +{ + +template +class FastVector +{ +public: + using iterator = T*; + using const_iterator = const T*; + + FastVector( size_t capacity ) + : m_ptr( (T*)tracy_malloc( sizeof( T ) * capacity ) ) + , m_size( 0 ) + , m_capacity( capacity ) + { + } + + FastVector( const FastVector& ) = delete; + FastVector( FastVector&& ) = delete; + + ~FastVector() + { + tracy_free( m_ptr ); + } + + FastVector& operator=( const FastVector& ) = delete; + FastVector& operator=( FastVector&& ) = delete; + + bool empty() const { return m_size == 0; } + size_t size() const { return m_size; } + + T* data() { return m_ptr; } + const T* data() const { return m_ptr; }; + + T* begin() { return m_ptr; } + const T* begin() const { return m_ptr; } + T* end() { return m_ptr + m_size; } + const T* end() const { return m_ptr + m_size; } + + T& front() { assert( m_size > 0 ); return m_ptr[0]; } + const T& front() const { assert( m_size > 0 ); return m_ptr[0]; } + + T& back() { assert( m_size > 0 ); return m_ptr[m_size - 1]; } + const T& back() const { assert( m_size > 0 ); return m_ptr[m_size - 1]; } + + T& operator[]( size_t idx ) { return m_ptr[idx]; } + const T& operator[]( size_t idx ) const { return m_ptr[idx]; } + + T* push_next() + { + T* ret; + if( m_size == m_capacity ) AllocMore(); + ret = m_ptr + m_size; + m_size++; + return ret; + } + + void clear() + { + m_size = 0; + } + +private: + tracy_no_inline void AllocMore() + { + m_capacity *= 2; + T* ptr = (T*)tracy_malloc( sizeof( T ) * m_capacity ); + memcpy( ptr, m_ptr, m_size * sizeof( T ) ); + tracy_free( m_ptr ); + m_ptr = ptr; + } + + T* m_ptr; + size_t m_size; + size_t m_capacity; +}; + +} + +#endif From faeecdd773b681c564e98786930645ce7c74ae1f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 19:53:05 +0200 Subject: [PATCH 06/58] Add serial queue to profiler. --- client/TracyProfiler.cpp | 3 ++- client/TracyProfiler.hpp | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index b9b8a561..c5a7d200 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -108,7 +108,7 @@ struct ThreadNameData; std::atomic init_order(104) s_threadNameData( nullptr ); #endif -static Profiler init_order(105) s_profiler; +Profiler init_order(105) s_profiler; enum { BulkSize = TargetFrameSize / QueueItemSize }; @@ -125,6 +125,7 @@ Profiler::Profiler() , m_bufferStart( 0 ) , m_itemBuf( (QueueItem*)tracy_malloc( sizeof( QueueItem ) * BulkSize ) ) , m_lz4Buf( (char*)tracy_malloc( LZ4Size + sizeof( lz4sz_t ) ) ) + , m_serialQueue( 1024*1024 ) { assert( !s_instance ); s_instance = this; diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index ea3af51c..f03c51d2 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -7,7 +7,9 @@ #include #include "concurrentqueue.h" +#include "TracyFastVector.hpp" #include "../common/tracy_lz4.hpp" +#include "../common/tracy_benaphore.h" #include "../common/TracyQueue.hpp" #include "../common/TracyAlign.hpp" #include "../common/TracyAlloc.hpp" @@ -50,6 +52,9 @@ struct GpuCtxWrapper using Magic = moodycamel::ConcurrentQueueDefaultTraits::index_t; +class Profiler; +extern Profiler s_profiler; + class Profiler { public: @@ -252,6 +257,9 @@ private: QueueItem* m_itemBuf; char* m_lz4Buf; + + FastVector m_serialQueue; + NonRecursiveBenaphore m_serialLock; }; }; From 860e0e180966fb688d100f75d01136383a7fed6e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 19:53:24 +0200 Subject: [PATCH 07/58] Store memory operations in the serial queue. --- client/TracyProfiler.hpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index f03c51d2..eb8b7057 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -193,29 +193,31 @@ public: static tracy_force_inline void MemAlloc( const void* ptr, size_t size ) { - Magic magic; - auto& token = s_token.ptr; - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + const auto time = GetTime(); + const auto thread = GetThreadHandle(); + + s_profiler.m_serialLock.lock(); + auto item = s_profiler.m_serialQueue.push_next(); MemWrite( &item->hdr.type, QueueType::MemAlloc ); - MemWrite( &item->memAlloc.time, GetTime() ); - MemWrite( &item->memAlloc.thread, GetThreadHandle() ); + MemWrite( &item->memAlloc.time, time ); + MemWrite( &item->memAlloc.thread, thread ); MemWrite( &item->memAlloc.ptr, (uint64_t)ptr ); memcpy( &item->memAlloc.size, &size, 6 ); - tail.store( magic + 1, std::memory_order_release ); + s_profiler.m_serialLock.unlock(); } static tracy_force_inline void MemFree( const void* ptr ) { - Magic magic; - auto& token = s_token.ptr; - auto& tail = token->get_tail_index(); - auto item = token->enqueue_begin( magic ); + const auto time = GetTime(); + const auto thread = GetThreadHandle(); + + s_profiler.m_serialLock.lock(); + auto item = s_profiler.m_serialQueue.push_next(); MemWrite( &item->hdr.type, QueueType::MemFree ); - MemWrite( &item->memFree.time, GetTime() ); - MemWrite( &item->memFree.thread, GetThreadHandle() ); + MemWrite( &item->memFree.time, time ); + MemWrite( &item->memFree.thread, thread ); MemWrite( &item->memFree.ptr, (uint64_t)ptr ); - tail.store( magic + 1, std::memory_order_release ); + s_profiler.m_serialLock.unlock(); } static bool ShouldExit(); From 794f199bdc93e3b5e87261acca6642fb022d8309 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 20:04:35 +0200 Subject: [PATCH 08/58] Serial queue dequeuing. --- client/TracyProfiler.cpp | 35 +++++++++++++++++++++++++++++++---- client/TracyProfiler.hpp | 1 + 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index c5a7d200..c4625935 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -213,11 +214,12 @@ void Profiler::Worker() for(;;) { const auto status = Dequeue( token ); - if( status == ConnectionLost ) + const auto serialStatus = DequeueSerial(); + if( status == ConnectionLost || serialStatus == ConnectionLost ) { break; } - else if( status == QueueEmpty ) + else if( status == QueueEmpty && serialStatus == QueueEmpty ) { if( ShouldExit() ) break; if( m_bufferOffset != m_bufferStart ) CommitData(); @@ -235,11 +237,12 @@ void Profiler::Worker() for(;;) { const auto status = Dequeue( token ); - if( status == ConnectionLost ) + const auto serialStatus = DequeueSerial(); + if( status == ConnectionLost || serialStatus == ConnectionLost ) { break; } - else if( status == QueueEmpty ) + else if( status == QueueEmpty && serialStatus == QueueEmpty ) { if( m_bufferOffset != m_bufferStart ) CommitData(); break; @@ -267,6 +270,7 @@ void Profiler::Worker() } } while( Dequeue( token ) == Success ) {} + while( DequeueSerial() == Success ) {} if( m_bufferOffset != m_bufferStart ) { if( !CommitData() ) return; @@ -326,6 +330,29 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token ) return Success; } +Profiler::DequeueStatus Profiler::DequeueSerial() +{ + std::lock_guard lock( m_serialLock ); + const auto sz = m_serialQueue.size(); + if( sz > 0 ) + { + auto item = m_serialQueue.data(); + auto end = item + sz; + while( item != end ) + { + const auto idx = MemRead( &item->hdr.idx ); + if( !AppendData( item, QueueDataSize[idx] ) ) return ConnectionLost; + item++; + } + m_serialQueue.clear(); + } + else + { + return QueueEmpty; + } + return Success; +} + bool Profiler::AppendData( const void* data, size_t len ) { auto ret = true; diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index eb8b7057..0c420548 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -229,6 +229,7 @@ private: void Worker(); DequeueStatus Dequeue( moodycamel::ConsumerToken& token ); + DequeueStatus DequeueSerial(); bool AppendData( const void* data, size_t len ); bool CommitData(); bool NeedDataSize( size_t len ); From a574f98f0c8ade62e38f5204eb6bbe4afcfd0b16 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 20:13:01 +0200 Subject: [PATCH 09/58] Memory events are now serialized. --- server/TracyEvent.hpp | 3 -- server/TracyWorker.cpp | 79 ++++++------------------------------------ server/TracyWorker.hpp | 1 - 3 files changed, 10 insertions(+), 73 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 53eef83c..05a0a573 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -225,10 +225,7 @@ struct PlotData struct MemData { Vector data; - Vector postpone; - uint64_t postponeTime; flat_hash_map> active; - flat_hash_map> zombie; uint64_t high = std::numeric_limits::min(); uint64_t low = std::numeric_limits::max(); }; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 42b20a09..bdc79916 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -525,7 +525,6 @@ void Worker::Exec() if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0; HandlePostponedPlots(); - HandlePostponedMemory(); } auto t1 = std::chrono::high_resolution_clock::now(); @@ -1634,93 +1633,35 @@ void Worker::ProcessGpuResync( const QueueGpuResync& ev ) void Worker::ProcessMemAlloc( const QueueMemAlloc& ev ) { - MemEvent* mem; const auto time = TscTime( ev.time ); - auto it = m_data.memory.zombie.find( ev.ptr ); - if( it == m_data.memory.zombie.end() ) - { - mem = m_slab.Alloc(); - mem->ptr = ev.ptr; - mem->timeFree = -1; - mem->threadFree = 0; - } - else - { - mem = it->second; - m_data.memory.zombie.erase( it ); - } - + auto mem = m_slab.Alloc(); + mem->ptr = ev.ptr; mem->size = 0; memcpy( &mem->size, ev.size, 6 ); mem->timeAlloc = time; mem->threadAlloc = CompressThread( ev.thread ); + mem->timeFree = -1; + mem->threadFree = 0; m_data.memory.low = std::min( m_data.memory.low, mem->ptr ); m_data.memory.high = std::max( m_data.memory.high, mem->ptr + mem->size ); - assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); // this assert is not valid; memory may have been freed, but the information has not yet arrived + assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); m_data.memory.active.emplace( ev.ptr, mem ); - if( m_data.memory.data.empty() ) - { - m_data.memory.data.push_back( mem ); - } - else if( m_data.memory.data.back()->timeAlloc < time ) - { - m_data.memory.data.push_back_non_empty( mem ); - } - else - { - if( m_data.memory.postpone.empty() ) - { - m_data.memory.postponeTime = std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); - m_data.memory.postpone.push_back( mem ); - } - else - { - m_data.memory.postpone.push_back_non_empty( mem ); - } - } + assert( m_data.memory.data.empty() || m_data.memory.data.back()->timeAlloc <= time ); + m_data.memory.data.push_back( mem ); } void Worker::ProcessMemFree( const QueueMemFree& ev ) { - MemEvent* mem; - auto it = m_data.memory.active.find( ev.ptr ); - if( it == m_data.memory.active.end() ) - { - mem = m_slab.Alloc(); - mem->ptr = ev.ptr; - - assert( m_data.memory.zombie.find( ev.ptr ) == m_data.memory.zombie.end() ); // this assert is not valid; there may be multiple alloc+frees queued for the same address - m_data.memory.zombie.emplace( ev.ptr, mem ); - } - else - { - mem = it->second; - m_data.memory.active.erase( it ); - } - + assert( it != m_data.memory.active.end() ); + auto mem = it->second; mem->timeFree = TscTime( ev.time ); mem->threadFree = CompressThread( ev.thread ); -} - -void Worker::HandlePostponedMemory() -{ - auto& src = m_data.memory.postpone; - if( src.empty() ) return; - if( std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count() - m_data.memory.postponeTime < 100 ) return; - auto& dst = m_data.memory.data; - std::sort( src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l->timeAlloc < r->timeAlloc; } ); - const auto ds = std::lower_bound( dst.begin(), dst.end(), src.front()->timeAlloc, [] ( const auto& l, const auto& r ) { return l->timeAlloc < r; } ); - const auto dsd = std::distance( dst.begin(), ds ) ; - const auto de = std::lower_bound( ds, dst.end(), src.back()->timeAlloc, [] ( const auto& l, const auto& r ) { return l->timeAlloc < 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->timeAlloc < r->timeAlloc; } ); - src.clear(); + m_data.memory.active.erase( it ); } void Worker::ReadTimeline( FileRead& f, Vector& vec, uint16_t thread ) diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 9c0cae1a..46a6e0d4 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -209,7 +209,6 @@ private: void HandlePlotName( uint64_t name, char* str, size_t sz ); void HandlePostponedPlots(); - void HandlePostponedMemory(); StringLocation StoreString( char* str, size_t sz ); uint16_t CompressThreadNew( uint64_t thread ); From cd3bba80638d63f55f8ca1f6f6b80bef000ae505 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 20:25:09 +0200 Subject: [PATCH 10/58] Memory data accessor. --- server/TracyWorker.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 46a6e0d4..64b26a1e 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -114,6 +114,7 @@ public: const Vector& GetGpuData() const { return m_data.gpuData; } const Vector& GetPlots() const { return m_data.plots; } const Vector& GetThreadData() const { return m_data.threads; } + const MemData& GetMemData() const { return m_data.memory; } // Some zones may have incomplete timing data (only start time is available, end hasn't arrived yet). // GetZoneEnd() will try to infer the end time by looking at child zones (parent zone can't end From 2d00d9574394910a7b6c08521d1fe37805250dbe Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 20:27:56 +0200 Subject: [PATCH 11/58] Missing initializer. --- server/TracyView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 52ed2735..730daaf0 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -199,6 +199,7 @@ View::View( FileRead& f ) , m_gpuEnd( 0 ) , m_showOptions( false ) , m_showMessages( false ) + , m_showStatistics( false ) , m_drawGpuZones( true ) , m_drawZones( true ) , m_drawLocks( true ) From c686b86464532fdfc507d796d24ee36a32b65b86 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 20:34:21 +0200 Subject: [PATCH 12/58] Add rudimentary memory information window. --- server/TracyView.cpp | 14 ++++++++++++++ server/TracyView.hpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 730daaf0..a53acc67 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -168,6 +168,7 @@ View::View( const char* addr ) , m_showOptions( false ) , m_showMessages( false ) , m_showStatistics( false ) + , m_showMemory( false ) , m_drawGpuZones( true ) , m_drawZones( true ) , m_drawLocks( true ) @@ -200,6 +201,7 @@ View::View( FileRead& f ) , m_showOptions( false ) , m_showMessages( false ) , m_showStatistics( false ) + , m_showMemory( false ) , m_drawGpuZones( true ) , m_drawZones( true ) , m_drawLocks( true ) @@ -307,6 +309,8 @@ void View::DrawImpl() ImGui::SameLine(); if( ImGui::Button( "Statistics", ImVec2( bw, 0 ) ) ) m_showStatistics = true; ImGui::SameLine(); + if( ImGui::Button( "Memory", ImVec2( bw, 0 ) ) ) m_showMemory = true; + ImGui::SameLine(); ImGui::Text( "Frames: %-7" PRIu64 " Time span: %-10s View span: %-10s Zones: %-13s Queue delay: %s Timer resolution: %s", m_worker.GetFrameCount(), TimeToString( m_worker.GetLastTime() - m_worker.GetFrameBegin( 0 ) ), TimeToString( m_zvEnd - m_zvStart ), RealToString( m_worker.GetZoneCount(), true ), TimeToString( m_worker.GetDelay() ), TimeToString( m_worker.GetResolution() ) ); DrawFrames(); DrawZones(); @@ -321,6 +325,7 @@ void View::DrawImpl() if( m_showMessages ) DrawMessages(); if( m_findZone.show ) DrawFindZone(); if( m_showStatistics ) DrawStatistics(); + if( m_showMemory ) DrawMemory(); if( m_zoomAnim.active ) { @@ -3647,6 +3652,15 @@ void View::DrawStatistics() ImGui::End(); } +void View::DrawMemory() +{ + auto& mem = m_worker.GetMemData(); + + ImGui::Begin( "Memory", &m_showMemory ); + ImGui::Text( "Active allocations: %s", RealToString( mem.active.size(), true ) ); + ImGui::End(); +} + uint32_t View::GetZoneColor( const ZoneEvent& ev ) { const auto& srcloc = m_worker.GetSourceLocation( ev.srcloc ); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 0c3a74c2..3ad775f0 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -74,6 +74,7 @@ private: void DrawMessages(); void DrawFindZone(); void DrawStatistics(); + void DrawMemory(); void DrawInfoWindow(); void DrawZoneInfoWindow(); @@ -159,6 +160,7 @@ private: bool m_showOptions; bool m_showMessages; bool m_showStatistics; + bool m_showMemory; bool m_drawGpuZones; bool m_drawZones; bool m_drawLocks; From 9c403d9cc23a15bb4f857bf2edc56d881e0ba41e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 21:07:33 +0200 Subject: [PATCH 13/58] GetTime() calls also must be serialized. --- client/TracyProfiler.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 0c420548..9d254eac 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -193,13 +193,12 @@ public: static tracy_force_inline void MemAlloc( const void* ptr, size_t size ) { - const auto time = GetTime(); const auto thread = GetThreadHandle(); s_profiler.m_serialLock.lock(); auto item = s_profiler.m_serialQueue.push_next(); MemWrite( &item->hdr.type, QueueType::MemAlloc ); - MemWrite( &item->memAlloc.time, time ); + MemWrite( &item->memAlloc.time, GetTime() ); MemWrite( &item->memAlloc.thread, thread ); MemWrite( &item->memAlloc.ptr, (uint64_t)ptr ); memcpy( &item->memAlloc.size, &size, 6 ); @@ -208,13 +207,12 @@ public: static tracy_force_inline void MemFree( const void* ptr ) { - const auto time = GetTime(); const auto thread = GetThreadHandle(); s_profiler.m_serialLock.lock(); auto item = s_profiler.m_serialQueue.push_next(); MemWrite( &item->hdr.type, QueueType::MemFree ); - MemWrite( &item->memFree.time, time ); + MemWrite( &item->memFree.time, GetTime() ); MemWrite( &item->memFree.thread, thread ); MemWrite( &item->memFree.ptr, (uint64_t)ptr ); s_profiler.m_serialLock.unlock(); From 20824a200cb12927f36477e210e9e2eb6c59afdd Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 21:24:30 +0200 Subject: [PATCH 14/58] Implement search for memory address. --- server/TracyView.cpp | 116 +++++++++++++++++++++++++++++++++++++++++-- server/TracyView.hpp | 11 ++-- 2 files changed, 119 insertions(+), 8 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index a53acc67..26f9ac78 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -168,7 +168,6 @@ View::View( const char* addr ) , m_showOptions( false ) , m_showMessages( false ) , m_showStatistics( false ) - , m_showMemory( false ) , m_drawGpuZones( true ) , m_drawZones( true ) , m_drawLocks( true ) @@ -201,7 +200,6 @@ View::View( FileRead& f ) , m_showOptions( false ) , m_showMessages( false ) , m_showStatistics( false ) - , m_showMemory( false ) , m_drawGpuZones( true ) , m_drawZones( true ) , m_drawLocks( true ) @@ -309,7 +307,7 @@ void View::DrawImpl() ImGui::SameLine(); if( ImGui::Button( "Statistics", ImVec2( bw, 0 ) ) ) m_showStatistics = true; ImGui::SameLine(); - if( ImGui::Button( "Memory", ImVec2( bw, 0 ) ) ) m_showMemory = true; + if( ImGui::Button( "Memory", ImVec2( bw, 0 ) ) ) m_memInfo.show = true; ImGui::SameLine(); ImGui::Text( "Frames: %-7" PRIu64 " Time span: %-10s View span: %-10s Zones: %-13s Queue delay: %s Timer resolution: %s", m_worker.GetFrameCount(), TimeToString( m_worker.GetLastTime() - m_worker.GetFrameBegin( 0 ) ), TimeToString( m_zvEnd - m_zvStart ), RealToString( m_worker.GetZoneCount(), true ), TimeToString( m_worker.GetDelay() ), TimeToString( m_worker.GetResolution() ) ); DrawFrames(); @@ -325,7 +323,7 @@ void View::DrawImpl() if( m_showMessages ) DrawMessages(); if( m_findZone.show ) DrawFindZone(); if( m_showStatistics ) DrawStatistics(); - if( m_showMemory ) DrawMemory(); + if( m_memInfo.show ) DrawMemory(); if( m_zoomAnim.active ) { @@ -3656,8 +3654,116 @@ void View::DrawMemory() { auto& mem = m_worker.GetMemData(); - ImGui::Begin( "Memory", &m_showMemory ); + ImGui::Begin( "Memory", &m_memInfo.show ); + ImGui::Text( "Active allocations: %s", RealToString( mem.active.size(), true ) ); + + ImGui::InputText( "", m_memInfo.pattern, 1024 ); + ImGui::SameLine(); + + if( ImGui::Button( "Find" ) ) + { + m_memInfo.ptrFind = strtoull( m_memInfo.pattern, nullptr, 0 ); + } + ImGui::SameLine(); + if( ImGui::Button( "Clear" ) ) + { + m_memInfo.ptrFind = 0; + m_memInfo.pattern[0] = '\0'; + } + + if( m_memInfo.ptrFind != 0 ) + { + std::vector match; + for( auto& v : mem.data ) + { + if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind ) + { + match.emplace_back( v ); + } + } + + ImGui::Separator(); + if( match.empty() ) + { + ImGui::Text( "Found no allocations at given address" ); + } + else + { + bool expand = ImGui::TreeNodeEx( "Allocations", ImGuiTreeNodeFlags_DefaultOpen ); + ImGui::SameLine(); + ImGui::TextDisabled( "(%s)", RealToString( match.size(), true ) ); + if( expand ) + { + ImGui::Columns( 5 ); + ImGui::Text( "Address" ); + ImGui::NextColumn(); + ImGui::Text( "Size" ); + ImGui::NextColumn(); + ImGui::Text( "Appeared at" ); + ImGui::NextColumn(); + ImGui::Text( "Duration" ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "Active allocations are displayed using green color." ); + ImGui::EndTooltip(); + } + + ImGui::NextColumn(); + ImGui::Text( "Thread" ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "Shows one thread if alloc and free was performed on the same thread." ); + ImGui::Text( "Otherwise two threads are displayed in order: alloc, free." ); + ImGui::EndTooltip(); + } + ImGui::NextColumn(); + ImGui::Separator(); + for( auto& v : match ) + { + if( v->ptr == m_memInfo.ptrFind ) + { + ImGui::Text( "0x%08x", m_memInfo.ptrFind ); + } + else + { + ImGui::Text( "0x%08x+%" PRIu64, v->ptr, m_memInfo.ptrFind - v->ptr ); + } + ImGui::NextColumn(); + ImGui::Text( "%s", RealToString( v->size, true ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", TimeToString( v->timeAlloc - m_worker.GetFrameBegin( 0 ) ) ); + ImGui::NextColumn(); + if( v->timeFree < 0 ) + { + ImGui::TextColored( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "%s", TimeToString( m_worker.GetLastTime() - v->timeAlloc ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); + } + else + { + ImGui::Text( "%s", TimeToString( v->timeFree - v->timeAlloc ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); + if( v->threadAlloc != v->threadFree ) + { + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadFree ) ) ); + } + } + ImGui::NextColumn(); + } + ImGui::EndColumns(); + ImGui::TreePop(); + } + } + } + ImGui::End(); } diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 3ad775f0..7f6480a0 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -160,7 +160,6 @@ private: bool m_showOptions; bool m_showMessages; bool m_showStatistics; - bool m_showMemory; bool m_drawGpuZones; bool m_drawZones; bool m_drawLocks; @@ -174,13 +173,13 @@ private: struct { enum : uint64_t { Unselected = std::numeric_limits::max() - 1 }; - bool show; + bool show = false; std::vector match; std::map> threads; size_t processed; int selMatch = 0; uint64_t selThread = Unselected; - char pattern[1024] = { "" }; + char pattern[1024] = {}; bool logVal = false; bool logTime = false; bool cumulateTime = false; @@ -203,6 +202,12 @@ private: processed = 0; } } m_findZone; + + struct { + bool show = false; + char pattern[1024] = {}; + uint64_t ptrFind = 0; + } m_memInfo; }; } From 912cfdbc5ef0e31c029e80b9966baa2249395085 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 21:47:08 +0200 Subject: [PATCH 15/58] Search for zone present in given thread at given time. --- server/TracyView.cpp | 28 ++++++++++++++++++++++++++++ server/TracyView.hpp | 1 + 2 files changed, 29 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 26f9ac78..f08c9647 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4048,6 +4048,34 @@ uint64_t View::GetZoneThread( const GpuEvent& zone ) const return 0; } +const ZoneEvent* View::FindZoneAtTime( uint64_t thread, int64_t time ) const +{ + // TODO add thread rev-map + ThreadData* td = nullptr; + for( const auto& t : m_worker.GetThreadData() ) + { + if( t->id == thread ) + { + td = t; + break; + } + } + if( !td ) return nullptr; + + const Vector* timeline = &td->timeline; + if( timeline->empty() ) return nullptr; + ZoneEvent* ret = nullptr; + for(;;) + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), time, [] ( const auto& l, const auto& r ) { return l < r->start; } ); + if( it != timeline->begin() ) --it; + if( (*it)->start > time || ( (*it)->end >= 0 && (*it)->end < time ) ) return ret; + ret = *it; + if( (*it)->child.empty() ) return ret; + timeline = &(*it)->child; + } +} + #ifndef TRACY_NO_STATISTICS void View::FindZones() { diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 7f6480a0..159484fc 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -99,6 +99,7 @@ private: const GpuEvent* GetZoneParent( const GpuEvent& zone ) const; uint64_t GetZoneThread( const ZoneEvent& zone ) const; uint64_t GetZoneThread( const GpuEvent& zone ) const; + const ZoneEvent* FindZoneAtTime( uint64_t thread, int64_t time ) const; #ifndef TRACY_NO_STATISTICS void FindZones(); From 3f7abd478edc4f30b7ea5ff57c606e5742bd595f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 21:50:35 +0200 Subject: [PATCH 16/58] Display zone in which memory allocation took place. --- server/TracyView.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index f08c9647..21596ba5 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3695,7 +3695,7 @@ void View::DrawMemory() ImGui::TextDisabled( "(%s)", RealToString( match.size(), true ) ); if( expand ) { - ImGui::Columns( 5 ); + ImGui::Columns( 6 ); ImGui::Text( "Address" ); ImGui::NextColumn(); ImGui::Text( "Size" ); @@ -3724,7 +3724,10 @@ void View::DrawMemory() ImGui::EndTooltip(); } ImGui::NextColumn(); + ImGui::Text( "Zone" ); + ImGui::NextColumn(); ImGui::Separator(); + int idx = 0; for( auto& v : match ) { if( v->ptr == m_memInfo.ptrFind ) @@ -3757,6 +3760,36 @@ void View::DrawMemory() } } ImGui::NextColumn(); + auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadAlloc ), v->timeAlloc ); + if( !zone ) + { + ImGui::Text( "-" ); + } + else + { + const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); + const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); + ImGui::PushID( idx++ ); + auto sel = ImGui::Selectable( txt, false ); + auto hover = ImGui::IsItemHovered(); + ImGui::SameLine(); + ImGui::TextDisabled( "%s:%i", m_worker.GetString( srcloc.file ), srcloc.line ); + ImGui::PopID(); + if( sel ) + { + m_zoneInfoWindow = zone; + } + if( hover ) + { + m_zoneHighlight = zone; + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToZone( *zone ); + } + ZoneTooltip( *zone ); + } + } + ImGui::NextColumn(); } ImGui::EndColumns(); ImGui::TreePop(); From 8efc0a0a7122fb713bcfad5aa851c9064312ee8e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 22:00:57 +0200 Subject: [PATCH 17/58] Display proper hex value. --- server/TracyView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 21596ba5..d145da72 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3732,11 +3732,11 @@ void View::DrawMemory() { if( v->ptr == m_memInfo.ptrFind ) { - ImGui::Text( "0x%08x", m_memInfo.ptrFind ); + ImGui::Text( "0x%" PRIx64, m_memInfo.ptrFind ); } else { - ImGui::Text( "0x%08x+%" PRIu64, v->ptr, m_memInfo.ptrFind - v->ptr ); + ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->ptr, m_memInfo.ptrFind - v->ptr ); } ImGui::NextColumn(); ImGui::Text( "%s", RealToString( v->size, true ) ); From e3509b6eee8d59bf7ed4ceea510aa62d127c58dc Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 1 Apr 2018 23:57:18 +0200 Subject: [PATCH 18/58] Display total number of allocations. --- server/TracyView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index d145da72..aa788ff6 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3656,7 +3656,7 @@ void View::DrawMemory() ImGui::Begin( "Memory", &m_memInfo.show ); - ImGui::Text( "Active allocations: %s", RealToString( mem.active.size(), true ) ); + ImGui::Text( "Total allocations: %-10s Active allocations: %s", RealToString( mem.data.size(), true ), RealToString( mem.active.size(), true ) ); ImGui::InputText( "", m_memInfo.pattern, 1024 ); ImGui::SameLine(); From 52f59c90bf71b65f7fd47c39950f779f08bf5cce Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 00:00:49 +0200 Subject: [PATCH 19/58] Track memory usage. --- server/TracyEvent.hpp | 1 + server/TracyWorker.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 05a0a573..842a6941 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -228,6 +228,7 @@ struct MemData flat_hash_map> active; uint64_t high = std::numeric_limits::min(); uint64_t low = std::numeric_limits::max(); + uint64_t usage = 0; }; struct StringLocation diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index bdc79916..41b1cfaa 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1646,6 +1646,7 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev ) m_data.memory.low = std::min( m_data.memory.low, mem->ptr ); m_data.memory.high = std::max( m_data.memory.high, mem->ptr + mem->size ); + m_data.memory.usage += mem->size; assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); m_data.memory.active.emplace( ev.ptr, mem ); @@ -1661,6 +1662,7 @@ void Worker::ProcessMemFree( const QueueMemFree& ev ) auto mem = it->second; mem->timeFree = TscTime( ev.time ); mem->threadFree = CompressThread( ev.thread ); + m_data.memory.usage -= mem->size; m_data.memory.active.erase( it ); } From 5824b47a6660376969c4391f8b2ea4fd9caa5dba Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 00:02:45 +0200 Subject: [PATCH 20/58] Display memory usage. --- server/TracyView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index aa788ff6..4ced0317 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3656,7 +3656,7 @@ void View::DrawMemory() ImGui::Begin( "Memory", &m_memInfo.show ); - ImGui::Text( "Total allocations: %-10s Active allocations: %s", RealToString( mem.data.size(), true ), RealToString( mem.active.size(), true ) ); + ImGui::Text( "Total allocations: %-10s Active allocations: %-10s Memory usage: %s bytes", RealToString( mem.data.size(), true ), RealToString( mem.active.size(), true ), RealToString( mem.usage, true ) ); ImGui::InputText( "", m_memInfo.pattern, 1024 ); ImGui::SameLine(); From 68acc30bdd44773ce2454ad2eeafdd60f21c2cff Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 01:54:25 +0200 Subject: [PATCH 21/58] Add support for determining FileRead EOF. --- server/TracyFileRead.hpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/server/TracyFileRead.hpp b/server/TracyFileRead.hpp index 52c02849..a53342b5 100644 --- a/server/TracyFileRead.hpp +++ b/server/TracyFileRead.hpp @@ -38,12 +38,24 @@ public: } } + bool IsEOF() + { + if( m_lastBlock != BufSize && m_offset == m_lastBlock ) return true; + if( m_offset == BufSize ) + { + if( fseek( m_file, 1, SEEK_CUR ) != 0 ) return true; + fseek( m_file, -1, SEEK_CUR ); + } + return false; + } + private: FileRead( FILE* f ) : m_stream( LZ4_createStreamDecode() ) , m_file( f ) , m_offset( BufSize ) , m_active( 1 ) + , m_lastBlock( 0 ) {} tracy_force_inline void ReadSmall( void* ptr, size_t size ) @@ -65,7 +77,7 @@ private: uint32_t sz; fread( &sz, 1, sizeof( sz ), m_file ); fread( m_lz4buf, 1, sz, m_file ); - LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize ); + m_lastBlock = LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize ); } const auto sz = std::min( size, BufSize - m_offset ); @@ -84,6 +96,7 @@ private: char m_buf[2][BufSize]; size_t m_offset; uint8_t m_active; + int m_lastBlock; }; } From 1fa943d109f92e8375fc43b6fadeaf6f81af0e7b Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 02:05:16 +0200 Subject: [PATCH 22/58] Save/load memory data. --- server/TracyWorker.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 41b1cfaa..858f309f 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -243,6 +243,26 @@ Worker::Worker( FileRead& f ) f.Read( pd->data.data(), psz * sizeof( PlotItem ) ); m_data.plots.push_back_no_space_check( pd ); } + + // Support pre-0.3 traces + if( f.IsEOF() ) return; + + f.Read( &sz, sizeof( sz ) ); + m_data.memory.data.reserve( sz ); + for( uint64_t i=0; i(); + f.Read( mem, sizeof( MemEvent ) ); + m_data.memory.data.push_back_no_space_check( mem ); + + if( mem->timeFree < 0 ) + { + m_data.memory.active.emplace( mem->ptr, mem ); + } + } + f.Read( &m_data.memory.high, sizeof( m_data.memory.high ) ); + f.Read( &m_data.memory.low, sizeof( m_data.memory.low ) ); + f.Read( &m_data.memory.usage, sizeof( m_data.memory.usage ) ); } Worker::~Worker() @@ -1879,6 +1899,16 @@ void Worker::Write( FileWrite& f ) f.Write( &sz, sizeof( sz ) ); f.Write( plot->data.data(), sizeof( PlotItem ) * sz ); } + + sz = m_data.memory.data.size(); + f.Write( &sz, sizeof( sz ) ); + for( auto& mem : m_data.memory.data ) + { + f.Write( mem, sizeof( MemEvent ) ); + } + 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 ) ); } void Worker::WriteTimeline( FileWrite& f, const Vector& vec ) From c4a36398f6d72c6a72d2eb1ca7db31dc5af845f5 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 02:19:46 +0200 Subject: [PATCH 23/58] Move memory allocations table drawing to a separate function. --- server/TracyView.cpp | 189 +++++++++++++++++++++++-------------------- server/TracyView.hpp | 4 + 2 files changed, 104 insertions(+), 89 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 4ced0317..532384c7 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3650,6 +3650,102 @@ void View::DrawStatistics() ImGui::End(); } +template +void View::ListMemData( T ptr, T end, std::function DrawAddress ) +{ + ImGui::Columns( 6 ); + ImGui::Text( "Address" ); + ImGui::NextColumn(); + ImGui::Text( "Size" ); + ImGui::NextColumn(); + ImGui::Text( "Appeared at" ); + ImGui::NextColumn(); + ImGui::Text( "Duration" ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "Active allocations are displayed using green color." ); + ImGui::EndTooltip(); + } + + ImGui::NextColumn(); + ImGui::Text( "Thread" ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "Shows one thread if alloc and free was performed on the same thread." ); + ImGui::Text( "Otherwise two threads are displayed in order: alloc, free." ); + ImGui::EndTooltip(); + } + ImGui::NextColumn(); + ImGui::Text( "Zone" ); + ImGui::NextColumn(); + ImGui::Separator(); + int idx = 0; + while( ptr != end ) + { + auto v = DrawAddress( ptr ); + ImGui::NextColumn(); + ImGui::Text( "%s", RealToString( v->size, true ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", TimeToString( v->timeAlloc - m_worker.GetFrameBegin( 0 ) ) ); + ImGui::NextColumn(); + if( v->timeFree < 0 ) + { + ImGui::TextColored( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "%s", TimeToString( m_worker.GetLastTime() - v->timeAlloc ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); + } + else + { + ImGui::Text( "%s", TimeToString( v->timeFree - v->timeAlloc ) ); + ImGui::NextColumn(); + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); + if( v->threadAlloc != v->threadFree ) + { + ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadFree ) ) ); + } + } + ImGui::NextColumn(); + auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadAlloc ), v->timeAlloc ); + if( !zone ) + { + ImGui::Text( "-" ); + } + else + { + const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); + const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); + ImGui::PushID( idx++ ); + auto sel = ImGui::Selectable( txt, false ); + auto hover = ImGui::IsItemHovered(); + ImGui::SameLine(); + ImGui::TextDisabled( "%s:%i", m_worker.GetString( srcloc.file ), srcloc.line ); + ImGui::PopID(); + if( sel ) + { + m_zoneInfoWindow = zone; + } + if( hover ) + { + m_zoneHighlight = zone; + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToZone( *zone ); + } + ZoneTooltip( *zone ); + } + } + ImGui::NextColumn(); + ptr++; + } + ImGui::EndColumns(); +} + void View::DrawMemory() { auto& mem = m_worker.GetMemData(); @@ -3695,41 +3791,8 @@ void View::DrawMemory() ImGui::TextDisabled( "(%s)", RealToString( match.size(), true ) ); if( expand ) { - ImGui::Columns( 6 ); - ImGui::Text( "Address" ); - ImGui::NextColumn(); - ImGui::Text( "Size" ); - ImGui::NextColumn(); - ImGui::Text( "Appeared at" ); - ImGui::NextColumn(); - ImGui::Text( "Duration" ); - ImGui::SameLine(); - ImGui::TextDisabled( "(?)" ); - if( ImGui::IsItemHovered() ) - { - ImGui::BeginTooltip(); - ImGui::Text( "Active allocations are displayed using green color." ); - ImGui::EndTooltip(); - } - - ImGui::NextColumn(); - ImGui::Text( "Thread" ); - ImGui::SameLine(); - ImGui::TextDisabled( "(?)" ); - if( ImGui::IsItemHovered() ) - { - ImGui::BeginTooltip(); - ImGui::Text( "Shows one thread if alloc and free was performed on the same thread." ); - ImGui::Text( "Otherwise two threads are displayed in order: alloc, free." ); - ImGui::EndTooltip(); - } - ImGui::NextColumn(); - ImGui::Text( "Zone" ); - ImGui::NextColumn(); - ImGui::Separator(); - int idx = 0; - for( auto& v : match ) - { + ListMemData( match.begin(), match.end(), [this]( auto& it ) { + auto& v = *it; if( v->ptr == m_memInfo.ptrFind ) { ImGui::Text( "0x%" PRIx64, m_memInfo.ptrFind ); @@ -3738,60 +3801,8 @@ void View::DrawMemory() { ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->ptr, m_memInfo.ptrFind - v->ptr ); } - ImGui::NextColumn(); - ImGui::Text( "%s", RealToString( v->size, true ) ); - ImGui::NextColumn(); - ImGui::Text( "%s", TimeToString( v->timeAlloc - m_worker.GetFrameBegin( 0 ) ) ); - ImGui::NextColumn(); - if( v->timeFree < 0 ) - { - ImGui::TextColored( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "%s", TimeToString( m_worker.GetLastTime() - v->timeAlloc ) ); - ImGui::NextColumn(); - ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); - } - else - { - ImGui::Text( "%s", TimeToString( v->timeFree - v->timeAlloc ) ); - ImGui::NextColumn(); - ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadAlloc ) ) ); - if( v->threadAlloc != v->threadFree ) - { - ImGui::Text( "%s", m_worker.GetThreadString( m_worker.DecompressThread( v->threadFree ) ) ); - } - } - ImGui::NextColumn(); - auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadAlloc ), v->timeAlloc ); - if( !zone ) - { - ImGui::Text( "-" ); - } - else - { - const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); - const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); - ImGui::PushID( idx++ ); - auto sel = ImGui::Selectable( txt, false ); - auto hover = ImGui::IsItemHovered(); - ImGui::SameLine(); - ImGui::TextDisabled( "%s:%i", m_worker.GetString( srcloc.file ), srcloc.line ); - ImGui::PopID(); - if( sel ) - { - m_zoneInfoWindow = zone; - } - if( hover ) - { - m_zoneHighlight = zone; - if( ImGui::IsMouseClicked( 2 ) ) - { - ZoomToZone( *zone ); - } - ZoneTooltip( *zone ); - } - } - ImGui::NextColumn(); - } - ImGui::EndColumns(); + return v; + } ); ImGui::TreePop(); } } diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 159484fc..ce135e8e 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -2,6 +2,7 @@ #define __TRACYVIEW_HPP__ #include +#include #include #include #include @@ -76,6 +77,9 @@ private: void DrawStatistics(); void DrawMemory(); + template + void ListMemData( T ptr, T end, std::function DrawAddress ); + void DrawInfoWindow(); void DrawZoneInfoWindow(); void DrawGpuInfoWindow(); From e1682c767512bc4bed5fbf446a5d2166ab88d98e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 02:37:40 +0200 Subject: [PATCH 24/58] Draw active allocations list. --- server/TracyView.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 532384c7..abb427e3 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3808,6 +3808,16 @@ void View::DrawMemory() } } + ImGui::Separator(); + if( ImGui::TreeNode( "Active allocations" ) ) + { + ListMemData( mem.active.begin(), mem.active.end(), []( auto& v ) { + ImGui::Text( "0x%" PRIx64, v->second->ptr ); + return v->second; + } ); + ImGui::TreePop(); + } + ImGui::End(); } From f7ce3e795f2e6789ae658bec928a2e9ae136983b Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:29:56 +0200 Subject: [PATCH 25/58] Display zone if which allocation was freed. --- server/TracyView.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index abb427e3..331e2397 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3653,7 +3653,7 @@ void View::DrawStatistics() template void View::ListMemData( T ptr, T end, std::function DrawAddress ) { - ImGui::Columns( 6 ); + ImGui::Columns( 7 ); ImGui::Text( "Address" ); ImGui::NextColumn(); ImGui::Text( "Size" ); @@ -3682,7 +3682,9 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) ImGui::EndTooltip(); } ImGui::NextColumn(); - ImGui::Text( "Zone" ); + ImGui::Text( "Zone alloc" ); + ImGui::NextColumn(); + ImGui::Text( "Zone free" ); ImGui::NextColumn(); ImGui::Separator(); int idx = 0; @@ -3723,8 +3725,6 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) ImGui::PushID( idx++ ); auto sel = ImGui::Selectable( txt, false ); auto hover = ImGui::IsItemHovered(); - ImGui::SameLine(); - ImGui::TextDisabled( "%s:%i", m_worker.GetString( srcloc.file ), srcloc.line ); ImGui::PopID(); if( sel ) { @@ -3741,6 +3741,41 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) } } ImGui::NextColumn(); + if( v->timeFree < 0 ) + { + ImGui::TextColored( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "active" ); + } + else + { + auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadFree ), v->timeFree ); + if( !zone ) + { + ImGui::Text( "-" ); + } + else + { + const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); + const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); + ImGui::PushID( idx++ ); + auto sel = ImGui::Selectable( txt, false ); + auto hover = ImGui::IsItemHovered(); + ImGui::PopID(); + if( sel ) + { + m_zoneInfoWindow = zone; + } + if( hover ) + { + m_zoneHighlight = zone; + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToZone( *zone ); + } + ZoneTooltip( *zone ); + } + } + } + ImGui::NextColumn(); ptr++; } ImGui::EndColumns(); From 50eb5c4b8420bd03e045a9179154c59dcd360a4a Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:36:07 +0200 Subject: [PATCH 26/58] Highlight same zone alloc+free. --- server/TracyView.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 331e2397..4e196789 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3685,6 +3685,14 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) ImGui::Text( "Zone alloc" ); ImGui::NextColumn(); ImGui::Text( "Zone free" ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "If alloc and free is performed in the same zone, it is displayed in yellow color." ); + ImGui::EndTooltip(); + } ImGui::NextColumn(); ImGui::Separator(); int idx = 0; @@ -3747,31 +3755,41 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) } else { - auto zone = FindZoneAtTime( m_worker.DecompressThread( v->threadFree ), v->timeFree ); - if( !zone ) + auto zoneFree = FindZoneAtTime( m_worker.DecompressThread( v->threadFree ), v->timeFree ); + if( !zoneFree ) { ImGui::Text( "-" ); } else { - const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); + const auto& srcloc = m_worker.GetSourceLocation( zoneFree->srcloc ); const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); ImGui::PushID( idx++ ); - auto sel = ImGui::Selectable( txt, false ); + bool sel; + if( zoneFree == zone ) + { + sel = ImGui::Selectable( "", false ); + ImGui::SameLine(); + ImGui::TextColored( ImVec4( 1.f, 1.f, 0.6f, 1.f ), txt ); + } + else + { + sel = ImGui::Selectable( txt, false ); + } auto hover = ImGui::IsItemHovered(); ImGui::PopID(); if( sel ) { - m_zoneInfoWindow = zone; + m_zoneInfoWindow = zoneFree; } if( hover ) { - m_zoneHighlight = zone; + m_zoneHighlight = zoneFree; if( ImGui::IsMouseClicked( 2 ) ) { - ZoomToZone( *zone ); + ZoomToZone( *zoneFree ); } - ZoneTooltip( *zone ); + ZoneTooltip( *zoneFree ); } } } From 8cc446b578b77855b8f1144851e5986446de2b10 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:38:08 +0200 Subject: [PATCH 27/58] Highlight zones with opened zone info window. --- server/TracyView.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 4e196789..b458f2be 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3731,7 +3731,7 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) const auto& srcloc = m_worker.GetSourceLocation( zone->srcloc ); const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function ); ImGui::PushID( idx++ ); - auto sel = ImGui::Selectable( txt, false ); + auto sel = ImGui::Selectable( txt, m_zoneInfoWindow == zone ); auto hover = ImGui::IsItemHovered(); ImGui::PopID(); if( sel ) @@ -3768,13 +3768,13 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) bool sel; if( zoneFree == zone ) { - sel = ImGui::Selectable( "", false ); + sel = ImGui::Selectable( "", m_zoneInfoWindow == zoneFree ); ImGui::SameLine(); ImGui::TextColored( ImVec4( 1.f, 1.f, 0.6f, 1.f ), txt ); } else { - sel = ImGui::Selectable( txt, false ); + sel = ImGui::Selectable( txt, m_zoneInfoWindow == zoneFree ); } auto hover = ImGui::IsItemHovered(); ImGui::PopID(); From aa8980aacc2fb66922509e6a6b55fbb90d4d725a Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:44:45 +0200 Subject: [PATCH 28/58] Put memory allocations list into a child area. --- server/TracyView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index b458f2be..ab76a1b1 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3653,6 +3653,7 @@ void View::DrawStatistics() template void View::ListMemData( T ptr, T end, std::function DrawAddress ) { + ImGui::BeginChild( "##memScroll", ImVec2( 0, std::max( 200.f, ImGui::GetContentRegionAvail().y ) ) ); ImGui::Columns( 7 ); ImGui::Text( "Address" ); ImGui::NextColumn(); @@ -3797,6 +3798,7 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) ptr++; } ImGui::EndColumns(); + ImGui::EndChild(); } void View::DrawMemory() From 821b08fbe4aea22bf3e656f06c2a9f39b27b420d Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:52:36 +0200 Subject: [PATCH 29/58] Thread compression state is not preserved. --- server/TracyWorker.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 858f309f..44eaa5bb 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -252,7 +252,15 @@ Worker::Worker( FileRead& f ) for( uint64_t i=0; i(); - f.Read( mem, sizeof( MemEvent ) ); + f.Read( &mem->ptr, sizeof( mem->ptr ) ); + f.Read( &mem->size, sizeof( mem->size ) ); + f.Read( &mem->timeAlloc, sizeof( mem->timeAlloc ) ); + f.Read( &mem->timeFree, sizeof( mem->timeFree ) ); + uint64_t t; + f.Read( &t, sizeof( t ) ); + mem->threadAlloc = CompressThread( t ); + f.Read( &t, sizeof( t ) ); + mem->threadFree = CompressThread( t ); m_data.memory.data.push_back_no_space_check( mem ); if( mem->timeFree < 0 ) @@ -1904,7 +1912,14 @@ void Worker::Write( FileWrite& f ) f.Write( &sz, sizeof( sz ) ); for( auto& mem : m_data.memory.data ) { - f.Write( mem, sizeof( MemEvent ) ); + f.Write( &mem->ptr, sizeof( mem->ptr ) ); + f.Write( &mem->size, sizeof( mem->size ) ); + f.Write( &mem->timeAlloc, sizeof( mem->timeAlloc ) ); + f.Write( &mem->timeFree, sizeof( mem->timeFree ) ); + uint64_t t = DecompressThread( mem->threadAlloc ); + f.Write( &t, sizeof( t ) ); + t = DecompressThread( mem->threadFree ); + f.Write( &t, sizeof( t ) ); } f.Write( &m_data.memory.high, sizeof( m_data.memory.high ) ); f.Write( &m_data.memory.low, sizeof( m_data.memory.low ) ); From 38edf308fa1346b7b07dc45fcd68a18badd5292c Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 14:58:40 +0200 Subject: [PATCH 30/58] Display memory span. --- server/TracyView.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index ab76a1b1..1188d27b 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3807,7 +3807,11 @@ void View::DrawMemory() ImGui::Begin( "Memory", &m_memInfo.show ); - ImGui::Text( "Total allocations: %-10s Active allocations: %-10s Memory usage: %s bytes", RealToString( mem.data.size(), true ), RealToString( mem.active.size(), true ), RealToString( mem.usage, true ) ); + ImGui::Text( "Total allocations: %-15s Active allocations: %-15s Memory usage: %-15s Memory span: %s", + RealToString( mem.data.size(), true ), + RealToString( mem.active.size(), true ), + RealToString( mem.usage, true ), + RealToString( mem.high - mem.low, true ) ); ImGui::InputText( "", m_memInfo.pattern, 1024 ); ImGui::SameLine(); From c1aaec32d62198f4f0d382179098fad07d84abb1 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 15:45:11 +0200 Subject: [PATCH 31/58] Sort active allocations by appearance time. --- server/TracyView.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 1188d27b..92351bcc 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3870,9 +3870,17 @@ void View::DrawMemory() ImGui::Separator(); if( ImGui::TreeNode( "Active allocations" ) ) { - ListMemData( mem.active.begin(), mem.active.end(), []( auto& v ) { - ImGui::Text( "0x%" PRIx64, v->second->ptr ); - return v->second; + std::vector items; + items.reserve( mem.active.size() ); + for( auto& v : mem.active ) + { + items.emplace_back( v.second ); + } + std::sort( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc > rhs->timeAlloc; } ); + + ListMemData( items.begin(), items.end(), []( auto& v ) { + ImGui::Text( "0x%" PRIx64, (*v)->ptr ); + return *v; } ); ImGui::TreePop(); } From e80891e36d65299a969cc32cc21c33ad4ec01991 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 16:07:33 +0200 Subject: [PATCH 32/58] Allow restricting displayed allocs by time. --- server/TracyView.cpp | 87 ++++++++++++++++++++++++++++++++------------ server/TracyView.hpp | 1 + 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 92351bcc..395041fb 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3826,30 +3826,53 @@ void View::DrawMemory() m_memInfo.ptrFind = 0; m_memInfo.pattern[0] = '\0'; } - - if( m_memInfo.ptrFind != 0 ) + ImGui::SameLine(); + ImGui::Checkbox( "Restrict time", &m_memInfo.restrictTime ); + ImGui::SameLine(); + ImGui::TextDisabled( "(?)" ); + if( ImGui::IsItemHovered() ) { - std::vector match; - for( auto& v : mem.data ) - { - if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind ) - { - match.emplace_back( v ); - } - } + ImGui::BeginTooltip(); + ImGui::Text( "Don't show allocations beyond end of timeline display." ); + ImGui::EndTooltip(); + } - ImGui::Separator(); - if( match.empty() ) + ImGui::Separator(); + if( ImGui::TreeNodeEx( "Allocations", ImGuiTreeNodeFlags_DefaultOpen ) ) + { + if( m_memInfo.ptrFind != 0 ) { - ImGui::Text( "Found no allocations at given address" ); - } - else - { - bool expand = ImGui::TreeNodeEx( "Allocations", ImGuiTreeNodeFlags_DefaultOpen ); - ImGui::SameLine(); - ImGui::TextDisabled( "(%s)", RealToString( match.size(), true ) ); - if( expand ) + std::vector match; + match.reserve( mem.active.size() ); // heuristic + if( m_memInfo.restrictTime ) { + for( auto& v : mem.data ) + { + if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind && v->timeAlloc < m_zvEnd ) + { + match.emplace_back( v ); + } + } + } + else + { + for( auto& v : mem.data ) + { + if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind ) + { + match.emplace_back( v ); + } + } + } + + if( match.empty() ) + { + ImGui::Text( "Found no allocations at given address" ); + } + else + { + ImGui::SameLine(); + ImGui::TextDisabled( "(%s)", RealToString( match.size(), true ) ); ListMemData( match.begin(), match.end(), [this]( auto& it ) { auto& v = *it; if( v->ptr == m_memInfo.ptrFind ) @@ -3862,9 +3885,9 @@ void View::DrawMemory() } return v; } ); - ImGui::TreePop(); } } + ImGui::TreePop(); } ImGui::Separator(); @@ -3872,11 +3895,27 @@ void View::DrawMemory() { std::vector items; items.reserve( mem.active.size() ); - for( auto& v : mem.active ) + if( m_memInfo.restrictTime ) { - items.emplace_back( v.second ); + for( auto& v : mem.data ) + { + if( v->timeAlloc < m_zvEnd && ( v->timeFree > m_zvEnd || v->timeFree < 0 ) ) + { + items.emplace_back( v ); + } + } } - std::sort( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc > rhs->timeAlloc; } ); + else + { + for( auto& v : mem.active ) + { + items.emplace_back( v.second ); + } + std::sort( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); + } + + ImGui::SameLine(); + ImGui::TextDisabled( "(%s)", RealToString( items.size(), true ) ); ListMemData( items.begin(), items.end(), []( auto& v ) { ImGui::Text( "0x%" PRIx64, (*v)->ptr ); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index ce135e8e..bdec35d6 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -212,6 +212,7 @@ private: bool show = false; char pattern[1024] = {}; uint64_t ptrFind = 0; + bool restrictTime = false; } m_memInfo; }; From 7b194d2349b612b8261a75aba77bd767eb2a8051 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 16:09:44 +0200 Subject: [PATCH 33/58] Don't use std::sort. --- server/TracyView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 395041fb..d69ce948 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -2511,7 +2511,7 @@ void View::DrawZoneInfoWindow() cti[i] = uint32_t( i ); } - std::sort( cti.get(), cti.get() + ev.child.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } ); + pdqsort_branchless( cti.get(), cti.get() + ev.child.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } ); if( !ev.child.empty() ) { @@ -2670,7 +2670,7 @@ void View::DrawGpuInfoWindow() cti[i] = uint32_t( i ); } - std::sort( cti.get(), cti.get() + ev.child.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } ); + pdqsort_branchless( cti.get(), cti.get() + ev.child.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } ); if( !ev.child.empty() ) { @@ -3484,7 +3484,7 @@ void View::DrawFindZone() } if( m_findZone.sortByCounts ) { - std::sort( threads.begin(), threads.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.size() > rhs->second.size(); } ); + pdqsort_branchless( threads.begin(), threads.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.size() > rhs->second.size(); } ); } ImGui::BeginChild( "##zonesScroll", ImVec2( ImGui::GetWindowContentRegionWidth(), std::max( 200.f, ImGui::GetContentRegionAvail().y ) ) ); @@ -3911,7 +3911,7 @@ void View::DrawMemory() { items.emplace_back( v.second ); } - std::sort( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); + pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); } ImGui::SameLine(); From 670744f852b98e8101a4c0fa1992aa29769fd26f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 16:21:24 +0200 Subject: [PATCH 34/58] Move alloc cutoff to middle of timeline. --- server/TracyView.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index d69ce948..52b33b1e 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -1092,6 +1092,13 @@ void View::DrawZones() auto& io = ImGui::GetIO(); draw->AddLine( ImVec2( io.MousePos.x, linepos.y ), ImVec2( io.MousePos.x, linepos.y + lineh ), 0x33FFFFFF ); } + + if( m_memInfo.show && m_memInfo.restrictTime ) + { + const auto zvMid = ( m_zvEnd - m_zvStart ) / 2; + auto& io = ImGui::GetIO(); + draw->AddLine( ImVec2( wpos.x + zvMid * pxns, linepos.y ), ImVec2( wpos.x + zvMid * pxns, linepos.y + lineh ), 0x88FF44FF ); + } } int View::DrawZoneLevel( const Vector& vec, bool hover, double pxns, const ImVec2& wpos, int _offset, int depth ) @@ -3833,10 +3840,12 @@ void View::DrawMemory() if( ImGui::IsItemHovered() ) { ImGui::BeginTooltip(); - ImGui::Text( "Don't show allocations beyond end of timeline display." ); + ImGui::Text( "Don't show allocations beyond the middle of timeline display." ); ImGui::EndTooltip(); } + const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; + ImGui::Separator(); if( ImGui::TreeNodeEx( "Allocations", ImGuiTreeNodeFlags_DefaultOpen ) ) { @@ -3848,7 +3857,7 @@ void View::DrawMemory() { for( auto& v : mem.data ) { - if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind && v->timeAlloc < m_zvEnd ) + if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind && v->timeAlloc < zvMid ) { match.emplace_back( v ); } @@ -3899,7 +3908,7 @@ void View::DrawMemory() { for( auto& v : mem.data ) { - if( v->timeAlloc < m_zvEnd && ( v->timeFree > m_zvEnd || v->timeFree < 0 ) ) + if( v->timeAlloc < zvMid && ( v->timeFree > zvMid || v->timeFree < 0 ) ) { items.emplace_back( v ); } From bf249de26675c519e4d90c906c9c79d465b11545 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 16:30:03 +0200 Subject: [PATCH 35/58] Display memory usage by active allocations. --- server/TracyView.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 52b33b1e..f2ab9915 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3902,6 +3902,7 @@ void View::DrawMemory() ImGui::Separator(); if( ImGui::TreeNode( "Active allocations" ) ) { + uint64_t total = 0; std::vector items; items.reserve( mem.active.size() ); if( m_memInfo.restrictTime ) @@ -3911,6 +3912,7 @@ void View::DrawMemory() if( v->timeAlloc < zvMid && ( v->timeFree > zvMid || v->timeFree < 0 ) ) { items.emplace_back( v ); + total += v->size; } } } @@ -3921,10 +3923,12 @@ void View::DrawMemory() items.emplace_back( v.second ); } pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); + total = mem.usage; } ImGui::SameLine(); ImGui::TextDisabled( "(%s)", RealToString( items.size(), true ) ); + ImGui::Text( "Memory usage: %s", RealToString( total, true ) ); ListMemData( items.begin(), items.end(), []( auto& v ) { ImGui::Text( "0x%" PRIx64, (*v)->ptr ); From 78cd86dd69bb8f2721b8d6bbb659fe19b6af4f8e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 18:14:59 +0200 Subject: [PATCH 36/58] Memory pages bitmap calculation. --- server/TracyView.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++ server/TracyView.hpp | 2 ++ 2 files changed, 78 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index f2ab9915..2b419673 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3940,6 +3940,82 @@ void View::DrawMemory() ImGui::End(); } +enum { ChunkBits = 10 }; +enum { ChunkSize = 1 << ChunkBits }; +enum { PageBits = 10 }; +enum { PageChunkBits = ChunkBits + PageBits }; +enum { PageSize = 1 << PageChunkBits }; +enum { PageMask = PageSize - 1 }; + +static tracy_force_inline void PreparePage( Vector& page ) +{ + if( page.empty() ) + { + page.reserve_and_use( ChunkSize ); + memset( page.data(), 0, ChunkSize ); + } +} + +Vector> View::GetMemoryPages() const +{ + Vector> ret; + + const auto& mem = m_worker.GetMemData(); + const auto span = mem.high - mem.low; + const auto pages = ( span / PageSize ) + 1; + + ret.reserve_and_use( pages ); + memset( ret.data(), 0, pages * sizeof( Vector ) ); + + for( auto& alloc : mem.data ) + { + const auto a0 = alloc->ptr - mem.low; + const auto a1 = a0 + alloc->size; + const auto p0 = a0 >> PageChunkBits; + const auto p1 = a1 >> PageChunkBits; + + int8_t val = alloc->timeFree < 0 ? 1 : -1; + + if( p0 == p1 ) + { + auto& page = ret[p0]; + PreparePage( page ); + const auto b0 = a0 & PageMask; + const auto b1 = a1 & PageMask; + const auto c0 = b0 >> ChunkBits; + const auto c1 = ( b1 >> ChunkBits ) + 1; + memset( page.data() + c0, val, c1 - c0 ); + } + else + { + { + auto& page = ret[p0]; + PreparePage( page ); + const auto b0 = a0 & PageMask; + const auto c0 = b0 >> ChunkBits; + memset( page.data() + c0, val, ChunkSize - c0 ); + } + + for( uint64_t i=p0+1; i> ChunkBits ) + 1; + memset( page.data(), val, c1 ); + } + } + } + + return ret; +} + uint32_t View::GetZoneColor( const ZoneEvent& ev ) { const auto& srcloc = m_worker.GetSourceLocation( ev.srcloc ); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index bdec35d6..d1be0c07 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -109,6 +109,8 @@ private: void FindZones(); #endif + Vector> GetMemoryPages() const; + flat_hash_map> m_visible; flat_hash_map> m_showFull; From 1c441824fd175e4f2c182a202300cc9959178e2d Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 18:40:59 +0200 Subject: [PATCH 37/58] Display memory map. --- server/TracyView.cpp | 90 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 2b419673..e0546e99 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3808,6 +3808,13 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) ImGui::EndChild(); } +enum { ChunkBits = 10 }; +enum { ChunkSize = 1 << ChunkBits }; +enum { PageBits = 10 }; +enum { PageChunkBits = ChunkBits + PageBits }; +enum { PageSize = 1 << PageChunkBits }; +enum { PageMask = PageSize - 1 }; + void View::DrawMemory() { auto& mem = m_worker.GetMemData(); @@ -3937,16 +3944,85 @@ void View::DrawMemory() ImGui::TreePop(); } + ImGui::Separator(); + if( ImGui::TreeNode( "Memory map" ) ) + { + auto pages = GetMemoryPages(); + + size_t lines = pages.size(); + size_t i = 0; + while( i < pages.size() ) + { + if( pages[i].empty() ) + { + i++; + while( pages[i].empty() ) + { + lines--; + i++; + } + } + else + { + i++; + } + } + + ImGui::BeginChild( "##memMap", ImVec2( ChunkSize + 2, lines + 2 ), false ); + auto draw = ImGui::GetWindowDrawList(); + const auto wpos = ImGui::GetCursorScreenPos() + ImVec2( 1, 1 ); + draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( ChunkSize + 1, lines + 1 ), 0xFF888888 ); + draw->AddRectFilled( wpos, wpos + ImVec2( ChunkSize, lines ), 0xFF666666 ); + + size_t line = 0; + i = 0; + while( i < pages.size() ) + { + auto& page = pages[i]; + if( page.empty() ) + { + i++; + draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( ChunkSize, line ), 0xFF555555 ); + line++; + while( pages[i].empty() ) i++; + } + else + { + size_t idx = 0; + while( idx < ChunkSize ) + { + if( page[idx] == 0 ) + { + do + { + idx++; + } + while( idx < ChunkSize && page[idx] == 0 ); + } + else + { + auto val = page[idx]; + const auto i0 = idx; + do + { + idx++; + } + while( idx < ChunkSize && page[idx] == val ); + draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), val > 0 ? 0xFF44FF44 : 0xFF4444FF ); + } + } + line++; + i++; + } + } + + ImGui::EndChild(); + ImGui::TreePop(); + } + ImGui::End(); } -enum { ChunkBits = 10 }; -enum { ChunkSize = 1 << ChunkBits }; -enum { PageBits = 10 }; -enum { PageChunkBits = ChunkBits + PageBits }; -enum { PageSize = 1 << PageChunkBits }; -enum { PageMask = PageSize - 1 }; - static tracy_force_inline void PreparePage( Vector& page ) { if( page.empty() ) From a2a6386491263772bd96da13e3248df4d478fad0 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 18:57:24 +0200 Subject: [PATCH 38/58] Allow time restricting memory map. --- server/TracyView.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index e0546e99..e5f102b6 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4043,14 +4043,18 @@ Vector> View::GetMemoryPages() const ret.reserve_and_use( pages ); memset( ret.data(), 0, pages * sizeof( Vector ) ); + const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; + for( auto& alloc : mem.data ) { + if( m_memInfo.restrictTime && alloc->timeAlloc > zvMid ) continue; + const auto a0 = alloc->ptr - mem.low; const auto a1 = a0 + alloc->size; const auto p0 = a0 >> PageChunkBits; const auto p1 = a1 >> PageChunkBits; - int8_t val = alloc->timeFree < 0 ? 1 : -1; + int8_t val = alloc->timeFree < 0 ? 1 : ( m_memInfo.restrictTime ? ( alloc->timeFree > zvMid ? 1 : -1 ) : -1 ); if( p0 == p1 ) { From 78ebf37039460753b8964231abec054d18083cec Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 19:57:46 +0200 Subject: [PATCH 39/58] Use proper values for page map calculation. --- server/TracyView.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index e5f102b6..b50581ca 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3809,11 +3809,11 @@ void View::ListMemData( T ptr, T end, std::function DrawAddress ) } enum { ChunkBits = 10 }; -enum { ChunkSize = 1 << ChunkBits }; enum { PageBits = 10 }; +enum { PageSize = 1 << PageBits }; enum { PageChunkBits = ChunkBits + PageBits }; -enum { PageSize = 1 << PageChunkBits }; -enum { PageMask = PageSize - 1 }; +enum { PageChunkSize = 1 << PageChunkBits }; +enum { PageChunkMask = PageChunkSize - 1 }; void View::DrawMemory() { @@ -3968,11 +3968,11 @@ void View::DrawMemory() } } - ImGui::BeginChild( "##memMap", ImVec2( ChunkSize + 2, lines + 2 ), false ); + ImGui::BeginChild( "##memMap", ImVec2( PageSize + 2, lines + 2 ), false ); auto draw = ImGui::GetWindowDrawList(); const auto wpos = ImGui::GetCursorScreenPos() + ImVec2( 1, 1 ); - draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( ChunkSize + 1, lines + 1 ), 0xFF888888 ); - draw->AddRectFilled( wpos, wpos + ImVec2( ChunkSize, lines ), 0xFF666666 ); + draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( PageSize + 1, lines + 1 ), 0xFF888888 ); + draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF666666 ); size_t line = 0; i = 0; @@ -3982,14 +3982,14 @@ void View::DrawMemory() if( page.empty() ) { i++; - draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( ChunkSize, line ), 0xFF555555 ); + draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( PageSize, line ), 0xFF555555 ); line++; while( pages[i].empty() ) i++; } else { size_t idx = 0; - while( idx < ChunkSize ) + while( idx < PageSize ) { if( page[idx] == 0 ) { @@ -3997,7 +3997,7 @@ void View::DrawMemory() { idx++; } - while( idx < ChunkSize && page[idx] == 0 ); + while( idx < PageSize && page[idx] == 0 ); } else { @@ -4007,7 +4007,7 @@ void View::DrawMemory() { idx++; } - while( idx < ChunkSize && page[idx] == val ); + while( idx < PageSize && page[idx] == val ); draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), val > 0 ? 0xFF44FF44 : 0xFF4444FF ); } } @@ -4027,8 +4027,8 @@ static tracy_force_inline void PreparePage( Vector& page ) { if( page.empty() ) { - page.reserve_and_use( ChunkSize ); - memset( page.data(), 0, ChunkSize ); + page.reserve_and_use( PageSize ); + memset( page.data(), 0, PageSize ); } } @@ -4038,7 +4038,7 @@ Vector> View::GetMemoryPages() const const auto& mem = m_worker.GetMemData(); const auto span = mem.high - mem.low; - const auto pages = ( span / PageSize ) + 1; + const auto pages = ( span / PageChunkSize ) + 1; ret.reserve_and_use( pages ); memset( ret.data(), 0, pages * sizeof( Vector ) ); @@ -4060,8 +4060,8 @@ Vector> View::GetMemoryPages() const { auto& page = ret[p0]; PreparePage( page ); - const auto b0 = a0 & PageMask; - const auto b1 = a1 & PageMask; + const auto b0 = a0 & PageChunkMask; + const auto b1 = a1 & PageChunkMask; const auto c0 = b0 >> ChunkBits; const auto c1 = ( b1 >> ChunkBits ) + 1; memset( page.data() + c0, val, c1 - c0 ); @@ -4071,22 +4071,22 @@ Vector> View::GetMemoryPages() const { auto& page = ret[p0]; PreparePage( page ); - const auto b0 = a0 & PageMask; + const auto b0 = a0 & PageChunkMask; const auto c0 = b0 >> ChunkBits; - memset( page.data() + c0, val, ChunkSize - c0 ); + memset( page.data() + c0, val, PageSize - c0 ); } for( uint64_t i=p0+1; i> ChunkBits ) + 1; memset( page.data(), val, c1 ); } From 1bb1cf9e6c886b34ca3e54df3e3bfd3013ffa6cc Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 20:00:05 +0200 Subject: [PATCH 40/58] Display memory map information. --- server/TracyView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index b50581ca..704fb930 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3947,6 +3947,8 @@ void View::DrawMemory() ImGui::Separator(); if( ImGui::TreeNode( "Memory map" ) ) { + ImGui::Text( "Single pixel: %s KB Single line: %s KB", RealToString( ( 1 << ChunkBits ) / 1024, true ), RealToString( PageChunkSize / 1024, true ) ); + auto pages = GetMemoryPages(); size_t lines = pages.size(); From 81c84025a2ba5d05fc08dc90d3d74b3a7fb32611 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 2 Apr 2018 20:11:55 +0200 Subject: [PATCH 41/58] Fix calculation of lines. --- server/TracyView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 704fb930..cde1a73b 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3958,7 +3958,7 @@ void View::DrawMemory() if( pages[i].empty() ) { i++; - while( pages[i].empty() ) + while( i < pages.size() && pages[i].empty() ) { lines--; i++; From 6d40502068aa9648dddf51b7dc2fe5290a71441e Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 13:23:53 +0200 Subject: [PATCH 42/58] Execute direct write to memory, if only one byte. --- server/TracyView.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index cde1a73b..076fbb3a 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4065,8 +4065,15 @@ Vector> View::GetMemoryPages() const const auto b0 = a0 & PageChunkMask; const auto b1 = a1 & PageChunkMask; const auto c0 = b0 >> ChunkBits; - const auto c1 = ( b1 >> ChunkBits ) + 1; - memset( page.data() + c0, val, c1 - c0 ); + const auto c1 = b1 >> ChunkBits; + if( c0 == c1 ) + { + *( page.data() + c0 ) = val; + } + else + { + memset( page.data() + c0, val, c1 - c0 + 1 ); + } } else { From bc27c99a1e4c5498b7f814cfd9d60b052fd7f67c Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 13:30:56 +0200 Subject: [PATCH 43/58] Move page init to a non-inlined function. --- server/TracyView.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 076fbb3a..e28d8815 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4025,13 +4025,15 @@ void View::DrawMemory() ImGui::End(); } +static void PreparePageInit( Vector& page ) +{ + page.reserve_and_use( PageSize ); + memset( page.data(), 0, PageSize ); +} + static tracy_force_inline void PreparePage( Vector& page ) { - if( page.empty() ) - { - page.reserve_and_use( PageSize ); - memset( page.data(), 0, PageSize ); - } + if( page.empty() ) PreparePageInit( page ); } Vector> View::GetMemoryPages() const From bf99bff87d4342be09ca0df261387522ad7413e2 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 14:17:51 +0200 Subject: [PATCH 44/58] Store MemEvents directly in the vector. --- server/TracyEvent.hpp | 4 +-- server/TracyVector.hpp | 6 +++++ server/TracyView.cpp | 31 +++++++++++----------- server/TracyView.hpp | 2 +- server/TracyWorker.cpp | 60 +++++++++++++++++++++--------------------- 5 files changed, 55 insertions(+), 48 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 842a6941..7819f846 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -224,8 +224,8 @@ struct PlotData struct MemData { - Vector data; - flat_hash_map> active; + Vector data; + flat_hash_map> active; uint64_t high = std::numeric_limits::min(); uint64_t low = std::numeric_limits::max(); uint64_t usage = 0; diff --git a/server/TracyVector.hpp b/server/TracyVector.hpp index db2474f8..c96c251d 100644 --- a/server/TracyVector.hpp +++ b/server/TracyVector.hpp @@ -94,6 +94,12 @@ public: m_ptr[m_size++] = std::move( v ); } + T& push_next() + { + if( m_size == Capacity() ) AllocMore(); + return m_ptr[m_size++]; + } + T* insert( T* it, const T& v ) { assert( it >= m_ptr && it <= m_ptr + m_size ); diff --git a/server/TracyView.cpp b/server/TracyView.cpp index e28d8815..0132ffcf 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3658,7 +3658,7 @@ void View::DrawStatistics() } template -void View::ListMemData( T ptr, T end, std::function DrawAddress ) +void View::ListMemData( T ptr, T end, std::function DrawAddress ) { ImGui::BeginChild( "##memScroll", ImVec2( 0, std::max( 200.f, ImGui::GetContentRegionAvail().y ) ) ); ImGui::Columns( 7 ); @@ -3858,15 +3858,15 @@ void View::DrawMemory() { if( m_memInfo.ptrFind != 0 ) { - std::vector match; + std::vector match; match.reserve( mem.active.size() ); // heuristic if( m_memInfo.restrictTime ) { for( auto& v : mem.data ) { - if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind && v->timeAlloc < zvMid ) + if( v.ptr <= m_memInfo.ptrFind && v.ptr + v.size > m_memInfo.ptrFind && v.timeAlloc < zvMid ) { - match.emplace_back( v ); + match.emplace_back( &v ); } } } @@ -3874,9 +3874,9 @@ void View::DrawMemory() { for( auto& v : mem.data ) { - if( v->ptr <= m_memInfo.ptrFind && v->ptr + v->size > m_memInfo.ptrFind ) + if( v.ptr <= m_memInfo.ptrFind && v.ptr + v.size > m_memInfo.ptrFind ) { - match.emplace_back( v ); + match.emplace_back( &v ); } } } @@ -3910,24 +3910,25 @@ void View::DrawMemory() if( ImGui::TreeNode( "Active allocations" ) ) { uint64_t total = 0; - std::vector items; + std::vector items; items.reserve( mem.active.size() ); if( m_memInfo.restrictTime ) { for( auto& v : mem.data ) { - if( v->timeAlloc < zvMid && ( v->timeFree > zvMid || v->timeFree < 0 ) ) + if( v.timeAlloc < zvMid && ( v.timeFree > zvMid || v.timeFree < 0 ) ) { - items.emplace_back( v ); - total += v->size; + items.emplace_back( &v ); + total += v.size; } } } else { + auto ptr = mem.data.data(); for( auto& v : mem.active ) { - items.emplace_back( v.second ); + items.emplace_back( ptr + v.second ); } pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->timeAlloc < rhs->timeAlloc; } ); total = mem.usage; @@ -4051,14 +4052,14 @@ Vector> View::GetMemoryPages() const for( auto& alloc : mem.data ) { - if( m_memInfo.restrictTime && alloc->timeAlloc > zvMid ) continue; + if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) continue; - const auto a0 = alloc->ptr - mem.low; - const auto a1 = a0 + alloc->size; + const auto a0 = alloc.ptr - mem.low; + const auto a1 = a0 + alloc.size; const auto p0 = a0 >> PageChunkBits; const auto p1 = a1 >> PageChunkBits; - int8_t val = alloc->timeFree < 0 ? 1 : ( m_memInfo.restrictTime ? ( alloc->timeFree > zvMid ? 1 : -1 ) : -1 ); + int8_t val = alloc.timeFree < 0 ? 1 : ( m_memInfo.restrictTime ? ( alloc.timeFree > zvMid ? 1 : -1 ) : -1 ); if( p0 == p1 ) { diff --git a/server/TracyView.hpp b/server/TracyView.hpp index d1be0c07..30e32f63 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -78,7 +78,7 @@ private: void DrawMemory(); template - void ListMemData( T ptr, T end, std::function DrawAddress ); + void ListMemData( T ptr, T end, std::function DrawAddress ); void DrawInfoWindow(); void DrawZoneInfoWindow(); diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 44eaa5bb..93ec9937 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -248,10 +248,10 @@ Worker::Worker( FileRead& f ) if( f.IsEOF() ) return; f.Read( &sz, sizeof( sz ) ); - m_data.memory.data.reserve( sz ); + m_data.memory.data.reserve_and_use( sz ); + auto mem = m_data.memory.data.data(); for( uint64_t i=0; i(); f.Read( &mem->ptr, sizeof( mem->ptr ) ); f.Read( &mem->size, sizeof( mem->size ) ); f.Read( &mem->timeAlloc, sizeof( mem->timeAlloc ) ); @@ -261,12 +261,13 @@ Worker::Worker( FileRead& f ) mem->threadAlloc = CompressThread( t ); f.Read( &t, sizeof( t ) ); mem->threadFree = CompressThread( t ); - m_data.memory.data.push_back_no_space_check( mem ); if( mem->timeFree < 0 ) { - m_data.memory.active.emplace( mem->ptr, mem ); + m_data.memory.active.emplace( mem->ptr, i ); } + + mem++; } f.Read( &m_data.memory.high, sizeof( m_data.memory.high ) ); f.Read( &m_data.memory.low, sizeof( m_data.memory.low ) ); @@ -1663,34 +1664,33 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev ) { const auto time = TscTime( ev.time ); - auto mem = m_slab.Alloc(); - mem->ptr = ev.ptr; - mem->size = 0; - memcpy( &mem->size, ev.size, 6 ); - mem->timeAlloc = time; - mem->threadAlloc = CompressThread( ev.thread ); - mem->timeFree = -1; - mem->threadFree = 0; - - m_data.memory.low = std::min( m_data.memory.low, mem->ptr ); - m_data.memory.high = std::max( m_data.memory.high, mem->ptr + mem->size ); - m_data.memory.usage += mem->size; - assert( m_data.memory.active.find( ev.ptr ) == m_data.memory.active.end() ); - m_data.memory.active.emplace( ev.ptr, mem ); + assert( m_data.memory.data.empty() || m_data.memory.data.back().timeAlloc <= time ); - assert( m_data.memory.data.empty() || m_data.memory.data.back()->timeAlloc <= time ); - m_data.memory.data.push_back( mem ); + m_data.memory.active.emplace( ev.ptr, m_data.memory.data.size() ); + + auto& mem = m_data.memory.data.push_next(); + mem.ptr = ev.ptr; + mem.size = 0; + memcpy( &mem.size, ev.size, 6 ); + mem.timeAlloc = time; + mem.threadAlloc = CompressThread( ev.thread ); + mem.timeFree = -1; + mem.threadFree = 0; + + m_data.memory.low = std::min( m_data.memory.low, mem.ptr ); + m_data.memory.high = std::max( m_data.memory.high, mem.ptr + mem.size ); + m_data.memory.usage += mem.size; } void Worker::ProcessMemFree( const QueueMemFree& ev ) { auto it = m_data.memory.active.find( ev.ptr ); assert( it != m_data.memory.active.end() ); - auto mem = it->second; - mem->timeFree = TscTime( ev.time ); - mem->threadFree = CompressThread( ev.thread ); - m_data.memory.usage -= mem->size; + auto& mem = m_data.memory.data[it->second]; + mem.timeFree = TscTime( ev.time ); + mem.threadFree = CompressThread( ev.thread ); + m_data.memory.usage -= mem.size; m_data.memory.active.erase( it ); } @@ -1912,13 +1912,13 @@ void Worker::Write( FileWrite& f ) f.Write( &sz, sizeof( sz ) ); for( auto& mem : m_data.memory.data ) { - f.Write( &mem->ptr, sizeof( mem->ptr ) ); - f.Write( &mem->size, sizeof( mem->size ) ); - f.Write( &mem->timeAlloc, sizeof( mem->timeAlloc ) ); - f.Write( &mem->timeFree, sizeof( mem->timeFree ) ); - uint64_t t = DecompressThread( mem->threadAlloc ); + f.Write( &mem.ptr, sizeof( mem.ptr ) ); + f.Write( &mem.size, sizeof( mem.size ) ); + f.Write( &mem.timeAlloc, sizeof( mem.timeAlloc ) ); + f.Write( &mem.timeFree, sizeof( mem.timeFree ) ); + uint64_t t = DecompressThread( mem.threadAlloc ); f.Write( &t, sizeof( t ) ); - t = DecompressThread( mem->threadFree ); + t = DecompressThread( mem.threadFree ); f.Write( &t, sizeof( t ) ); } f.Write( &m_data.memory.high, sizeof( m_data.memory.high ) ); From 3ea56009001dca23a9c44873dcae2a4bf86d2868 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 16:45:55 +0200 Subject: [PATCH 45/58] Fix UB, lose type safety. --- client/TracyProfiler.cpp | 8 ++++---- common/TracyAlign.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index c4625935..9758c656 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -294,23 +294,23 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token ) while( item != end ) { uint64_t ptr; - const auto idx = MemRead( &item->hdr.idx ); + const auto idx = MemRead( &item->hdr.idx ); if( idx < (int)QueueType::Terminate ) { switch( (QueueType)idx ) { case QueueType::ZoneText: - ptr = MemRead( &item->zoneText.text ); + ptr = MemRead( &item->zoneText.text ); SendString( ptr, (const char*)ptr, QueueType::CustomStringData ); tracy_free( (void*)ptr ); break; case QueueType::Message: - ptr = MemRead( &item->message.text ); + ptr = MemRead( &item->message.text ); SendString( ptr, (const char*)ptr, QueueType::CustomStringData ); tracy_free( (void*)ptr ); break; case QueueType::ZoneBeginAllocSrcLoc: - ptr = MemRead( &item->zoneBegin.srcloc ); + ptr = MemRead( &item->zoneBegin.srcloc ); SendSourceLocationPayload( ptr ); tracy_free( (void*)ptr ); break; diff --git a/common/TracyAlign.hpp b/common/TracyAlign.hpp index 5e5ec034..2ab631e1 100644 --- a/common/TracyAlign.hpp +++ b/common/TracyAlign.hpp @@ -9,7 +9,7 @@ namespace tracy { template -tracy_force_inline T MemRead( T* ptr ) +tracy_force_inline T MemRead( void* ptr ) { T val; memcpy( &val, ptr, sizeof( T ) ); @@ -17,7 +17,7 @@ tracy_force_inline T MemRead( T* ptr ) } template -tracy_force_inline void MemWrite( T* ptr, T val ) +tracy_force_inline void MemWrite( void* ptr, T val ) { memcpy( ptr, &val, sizeof( T ) ); } From 7c4075c9ce4f76efc267f19504e3047e78df6268 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 17:57:12 +0200 Subject: [PATCH 46/58] Fix MemRead() call. --- client/TracyProfiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 9758c656..173cdc74 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -340,7 +340,7 @@ Profiler::DequeueStatus Profiler::DequeueSerial() auto end = item + sz; while( item != end ) { - const auto idx = MemRead( &item->hdr.idx ); + const auto idx = MemRead( &item->hdr.idx ); if( !AppendData( item, QueueDataSize[idx] ) ) return ConnectionLost; item++; } From 5ce3e44c777e701e92394cf2ae51bb424ed20c21 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 18:27:50 +0200 Subject: [PATCH 47/58] Calculate chunks in one place in code. --- server/TracyView.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 0132ffcf..a185fbaf 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4059,16 +4059,17 @@ Vector> View::GetMemoryPages() const const auto p0 = a0 >> PageChunkBits; const auto p1 = a1 >> PageChunkBits; + const auto b0 = a0 & PageChunkMask; + const auto b1 = a1 & PageChunkMask; + const auto c0 = b0 >> ChunkBits; + const auto c1 = b1 >> ChunkBits; + int8_t val = alloc.timeFree < 0 ? 1 : ( m_memInfo.restrictTime ? ( alloc.timeFree > zvMid ? 1 : -1 ) : -1 ); if( p0 == p1 ) { auto& page = ret[p0]; PreparePage( page ); - const auto b0 = a0 & PageChunkMask; - const auto b1 = a1 & PageChunkMask; - const auto c0 = b0 >> ChunkBits; - const auto c1 = b1 >> ChunkBits; if( c0 == c1 ) { *( page.data() + c0 ) = val; @@ -4083,8 +4084,6 @@ Vector> View::GetMemoryPages() const { auto& page = ret[p0]; PreparePage( page ); - const auto b0 = a0 & PageChunkMask; - const auto c0 = b0 >> ChunkBits; memset( page.data() + c0, val, PageSize - c0 ); } @@ -4098,9 +4097,7 @@ Vector> View::GetMemoryPages() const { auto& page = ret[p1]; PreparePage( page ); - const auto b1 = a1 & PageChunkMask; - const auto c1 = ( b1 >> ChunkBits ) + 1; - memset( page.data(), val, c1 ); + memset( page.data(), val, c1 + 1 ); } } } From f0573d68bd12a8803308efc45257ec96b8ca6980 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:17:32 +0200 Subject: [PATCH 48/58] Store memory pages in a contiguous memory area. --- server/TracyView.cpp | 87 ++++++++++++++++---------------------------- server/TracyView.hpp | 2 +- 2 files changed, 32 insertions(+), 57 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index a185fbaf..76bd77ab 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3952,22 +3952,25 @@ void View::DrawMemory() auto pages = GetMemoryPages(); - size_t lines = pages.size(); - size_t i = 0; - while( i < pages.size() ) + const int8_t empty[PageSize] = {}; + const auto sz = pages.size() / PageSize; + auto pgptr = pages.data(); + const auto end = pgptr + sz * PageSize; + size_t lines = sz; + while( pgptr != end ) { - if( pages[i].empty() ) + if( memcmp( empty, pgptr, PageSize ) == 0 ) { - i++; - while( i < pages.size() && pages[i].empty() ) + pgptr += PageSize; + while( pgptr != end && memcmp( empty, pgptr, PageSize ) == 0 ) { lines--; - i++; + pgptr += PageSize; } } else { - i++; + pgptr += PageSize; } } @@ -3978,44 +3981,43 @@ void View::DrawMemory() draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF666666 ); size_t line = 0; - i = 0; - while( i < pages.size() ) + pgptr = pages.data(); + while( pgptr != end ) { - auto& page = pages[i]; - if( page.empty() ) + if( memcmp( empty, pgptr, PageSize ) == 0 ) { - i++; + pgptr += PageSize; draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( PageSize, line ), 0xFF555555 ); line++; - while( pages[i].empty() ) i++; + while( pgptr != end && memcmp( empty, pgptr, PageSize ) == 0 ) pgptr += PageSize; } else { size_t idx = 0; while( idx < PageSize ) { - if( page[idx] == 0 ) + if( pgptr[idx] == 0 ) { do { idx++; } - while( idx < PageSize && page[idx] == 0 ); + while( idx < PageSize && pgptr[idx] == 0 ); } else { - auto val = page[idx]; + auto val = pgptr[idx]; const auto i0 = idx; do { idx++; } - while( idx < PageSize && page[idx] == val ); + while( idx < PageSize && pgptr[idx] == val ); draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), val > 0 ? 0xFF44FF44 : 0xFF4444FF ); } } line++; - i++; + pgptr += PageSize; } } @@ -4026,27 +4028,17 @@ void View::DrawMemory() ImGui::End(); } -static void PreparePageInit( Vector& page ) +Vector View::GetMemoryPages() const { - page.reserve_and_use( PageSize ); - memset( page.data(), 0, PageSize ); -} - -static tracy_force_inline void PreparePage( Vector& page ) -{ - if( page.empty() ) PreparePageInit( page ); -} - -Vector> View::GetMemoryPages() const -{ - Vector> ret; + Vector ret; const auto& mem = m_worker.GetMemData(); const auto span = mem.high - mem.low; const auto pages = ( span / PageChunkSize ) + 1; - ret.reserve_and_use( pages ); - memset( ret.data(), 0, pages * sizeof( Vector ) ); + ret.reserve_and_use( pages * PageSize ); + auto pgptr = ret.data(); + memset( pgptr, 0, pages * PageSize ); const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; @@ -4068,37 +4060,20 @@ Vector> View::GetMemoryPages() const if( p0 == p1 ) { - auto& page = ret[p0]; - PreparePage( page ); + auto page = pgptr + p0 * PageSize; if( c0 == c1 ) { - *( page.data() + c0 ) = val; + page[c0] = val; } else { - memset( page.data() + c0, val, c1 - c0 + 1 ); + memset( page + c0, val, c1 - c0 + 1 ); } } else { - { - auto& page = ret[p0]; - PreparePage( page ); - memset( page.data() + c0, val, PageSize - c0 ); - } - - for( uint64_t i=p0+1; i> GetMemoryPages() const; + Vector GetMemoryPages() const; flat_hash_map> m_visible; flat_hash_map> m_showFull; From 197e51372763272dd7d19bfb018c375aa382ff0c Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:34:48 +0200 Subject: [PATCH 49/58] Add a separate time restriction code path. --- server/TracyView.cpp | 87 +++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 76bd77ab..f93039ff 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4040,40 +4040,77 @@ Vector View::GetMemoryPages() const auto pgptr = ret.data(); memset( pgptr, 0, pages * PageSize ); - const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; - - for( auto& alloc : mem.data ) + if( m_memInfo.restrictTime ) { - if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) continue; - - const auto a0 = alloc.ptr - mem.low; - const auto a1 = a0 + alloc.size; - const auto p0 = a0 >> PageChunkBits; - const auto p1 = a1 >> PageChunkBits; - - const auto b0 = a0 & PageChunkMask; - const auto b1 = a1 & PageChunkMask; - const auto c0 = b0 >> ChunkBits; - const auto c1 = b1 >> ChunkBits; - - int8_t val = alloc.timeFree < 0 ? 1 : ( m_memInfo.restrictTime ? ( alloc.timeFree > zvMid ? 1 : -1 ) : -1 ); - - if( p0 == p1 ) + const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; + for( auto& alloc : mem.data ) { - auto page = pgptr + p0 * PageSize; - if( c0 == c1 ) + if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) continue; + + const auto a0 = alloc.ptr - mem.low; + const auto a1 = a0 + alloc.size; + const auto p0 = a0 >> PageChunkBits; + const auto p1 = a1 >> PageChunkBits; + + const auto b0 = a0 & PageChunkMask; + const auto b1 = a1 & PageChunkMask; + const auto c0 = b0 >> ChunkBits; + const auto c1 = b1 >> ChunkBits; + + int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); + + if( p0 == p1 ) { - page[c0] = val; + auto page = pgptr + p0 * PageSize; + if( c0 == c1 ) + { + page[c0] = val; + } + else + { + memset( page + c0, val, c1 - c0 + 1 ); + } } else { - memset( page + c0, val, c1 - c0 + 1 ); + auto page = pgptr + p0 * PageSize; + memset( page + c0, val, ( PageSize - c0 ) + PageSize * ( p1 - p0 - 1 ) + ( c1 + 1 ) ); } } - else + } + else + { + for( auto& alloc : mem.data ) { - auto page = pgptr + p0 * PageSize; - memset( page + c0, val, ( PageSize - c0 ) + PageSize * ( p1 - p0 - 1 ) + ( c1 + 1 ) ); + const auto a0 = alloc.ptr - mem.low; + const auto a1 = a0 + alloc.size; + const auto p0 = a0 >> PageChunkBits; + const auto p1 = a1 >> PageChunkBits; + + const auto b0 = a0 & PageChunkMask; + const auto b1 = a1 & PageChunkMask; + const auto c0 = b0 >> ChunkBits; + const auto c1 = b1 >> ChunkBits; + + int8_t val = alloc.timeFree < 0 ? 1 : -1; + + if( p0 == p1 ) + { + auto page = pgptr + p0 * PageSize; + if( c0 == c1 ) + { + page[c0] = val; + } + else + { + memset( page + c0, val, c1 - c0 + 1 ); + } + } + else + { + auto page = pgptr + p0 * PageSize; + memset( page + c0, val, ( PageSize - c0 ) + PageSize * ( p1 - p0 - 1 ) + ( c1 + 1 ) ); + } } } From a3dd90529ccbb6427cf2e5df2aee8ed72c5a083d Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:35:28 +0200 Subject: [PATCH 50/58] Rearrange memory reads. --- server/TracyView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index f93039ff..6a3746be 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4049,6 +4049,8 @@ Vector View::GetMemoryPages() const const auto a0 = alloc.ptr - mem.low; const auto a1 = a0 + alloc.size; + int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); + const auto p0 = a0 >> PageChunkBits; const auto p1 = a1 >> PageChunkBits; @@ -4057,8 +4059,6 @@ Vector View::GetMemoryPages() const const auto c0 = b0 >> ChunkBits; const auto c1 = b1 >> ChunkBits; - int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); - if( p0 == p1 ) { auto page = pgptr + p0 * PageSize; @@ -4084,6 +4084,8 @@ Vector View::GetMemoryPages() const { const auto a0 = alloc.ptr - mem.low; const auto a1 = a0 + alloc.size; + const int8_t val = alloc.timeFree < 0 ? 1 : -1; + const auto p0 = a0 >> PageChunkBits; const auto p1 = a1 >> PageChunkBits; @@ -4092,8 +4094,6 @@ Vector View::GetMemoryPages() const const auto c0 = b0 >> ChunkBits; const auto c1 = b1 >> ChunkBits; - int8_t val = alloc.timeFree < 0 ? 1 : -1; - if( p0 == p1 ) { auto page = pgptr + p0 * PageSize; From 22bd2923eb33f7b04eec15144881f3130e2d9765 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:35:43 +0200 Subject: [PATCH 51/58] Keep mem.low in a register. --- server/TracyView.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 6a3746be..f4cdf96d 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4040,6 +4040,8 @@ Vector View::GetMemoryPages() const auto pgptr = ret.data(); memset( pgptr, 0, pages * PageSize ); + const auto memlow = mem.low; + if( m_memInfo.restrictTime ) { const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; @@ -4047,7 +4049,7 @@ Vector View::GetMemoryPages() const { if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) continue; - const auto a0 = alloc.ptr - mem.low; + const auto a0 = alloc.ptr - memlow; const auto a1 = a0 + alloc.size; int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); @@ -4082,7 +4084,7 @@ Vector View::GetMemoryPages() const { for( auto& alloc : mem.data ) { - const auto a0 = alloc.ptr - mem.low; + const auto a0 = alloc.ptr - memlow; const auto a1 = a0 + alloc.size; const int8_t val = alloc.timeFree < 0 ? 1 : -1; From b78dc70b708ea19d491d6031a9340c8601d2d28f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:39:19 +0200 Subject: [PATCH 52/58] No need to split address into page and chunk. --- server/TracyView.cpp | 48 +++++++++----------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index f4cdf96d..480b55c7 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4053,30 +4053,16 @@ Vector View::GetMemoryPages() const const auto a1 = a0 + alloc.size; int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); - const auto p0 = a0 >> PageChunkBits; - const auto p1 = a1 >> PageChunkBits; + const auto c0 = a0 >> ChunkBits; + const auto c1 = a1 >> ChunkBits; - const auto b0 = a0 & PageChunkMask; - const auto b1 = a1 & PageChunkMask; - const auto c0 = b0 >> ChunkBits; - const auto c1 = b1 >> ChunkBits; - - if( p0 == p1 ) + if( c0 == c1 ) { - auto page = pgptr + p0 * PageSize; - if( c0 == c1 ) - { - page[c0] = val; - } - else - { - memset( page + c0, val, c1 - c0 + 1 ); - } + pgptr[c0] = val; } else { - auto page = pgptr + p0 * PageSize; - memset( page + c0, val, ( PageSize - c0 ) + PageSize * ( p1 - p0 - 1 ) + ( c1 + 1 ) ); + memset( pgptr + c0, val, c1 - c0 + 1 ); } } } @@ -4088,30 +4074,16 @@ Vector View::GetMemoryPages() const const auto a1 = a0 + alloc.size; const int8_t val = alloc.timeFree < 0 ? 1 : -1; - const auto p0 = a0 >> PageChunkBits; - const auto p1 = a1 >> PageChunkBits; + const auto c0 = a0 >> ChunkBits; + const auto c1 = a1 >> ChunkBits; - const auto b0 = a0 & PageChunkMask; - const auto b1 = a1 & PageChunkMask; - const auto c0 = b0 >> ChunkBits; - const auto c1 = b1 >> ChunkBits; - - if( p0 == p1 ) + if( c0 == c1 ) { - auto page = pgptr + p0 * PageSize; - if( c0 == c1 ) - { - page[c0] = val; - } - else - { - memset( page + c0, val, c1 - c0 + 1 ); - } + pgptr[c0] = val; } else { - auto page = pgptr + p0 * PageSize; - memset( page + c0, val, ( PageSize - c0 ) + PageSize * ( p1 - p0 - 1 ) + ( c1 + 1 ) ); + memset( pgptr + c0, val, c1 - c0 + 1 ); } } } From 1182a3fcb8b6f0dbbe2f73157c3da0d05efc2b33 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:40:06 +0200 Subject: [PATCH 53/58] Stop processing allocations if already at time end. --- server/TracyView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 480b55c7..1ee8e9ae 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -4047,7 +4047,7 @@ Vector View::GetMemoryPages() const const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2; for( auto& alloc : mem.data ) { - if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) continue; + if( m_memInfo.restrictTime && alloc.timeAlloc > zvMid ) break; const auto a0 = alloc.ptr - memlow; const auto a1 = a0 + alloc.size; From 189a4a2e32a725e6626eb3501890483c35a210fc Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 19:41:11 +0200 Subject: [PATCH 54/58] Page chunk mask is not needed anymore. --- server/TracyView.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 1ee8e9ae..6679b1f0 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3813,7 +3813,6 @@ enum { PageBits = 10 }; enum { PageSize = 1 << PageBits }; enum { PageChunkBits = ChunkBits + PageBits }; enum { PageChunkSize = 1 << PageChunkBits }; -enum { PageChunkMask = PageChunkSize - 1 }; void View::DrawMemory() { From bb299a50740903e5fadaafb12683389f11838fdd Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Tue, 3 Apr 2018 20:38:50 +0200 Subject: [PATCH 55/58] Desaturate older allocations on memory map. --- server/TracyView.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 6679b1f0..fd3d51dd 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3976,8 +3976,8 @@ void View::DrawMemory() ImGui::BeginChild( "##memMap", ImVec2( PageSize + 2, lines + 2 ), false ); auto draw = ImGui::GetWindowDrawList(); const auto wpos = ImGui::GetCursorScreenPos() + ImVec2( 1, 1 ); - draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( PageSize + 1, lines + 1 ), 0xFF888888 ); - draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF666666 ); + draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( PageSize + 1, lines + 1 ), 0xFF666666 ); + draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF444444 ); size_t line = 0; pgptr = pages.data(); @@ -3986,7 +3986,7 @@ void View::DrawMemory() if( memcmp( empty, pgptr, PageSize ) == 0 ) { pgptr += PageSize; - draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( PageSize, line ), 0xFF555555 ); + draw->AddLine( wpos + ImVec2( 0, line ), wpos + ImVec2( PageSize, line ), 0x11000000 ); line++; while( pgptr != end && memcmp( empty, pgptr, PageSize ) == 0 ) pgptr += PageSize; } @@ -4012,7 +4012,16 @@ void View::DrawMemory() idx++; } while( idx < PageSize && pgptr[idx] == val ); - draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), val > 0 ? 0xFF44FF44 : 0xFF4444FF ); + uint32_t color; + if( val > 0 ) + { + color = 0x44FF44 | ( ( 126 + val ) << 24 ); + } + else + { + color = 0x4444FF | ( ( 126 - val ) << 24 ); + } + draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), color ); } } line++; @@ -4050,7 +4059,11 @@ Vector View::GetMemoryPages() const const auto a0 = alloc.ptr - memlow; const auto a1 = a0 + alloc.size; - int8_t val = alloc.timeFree < 0 ? 1 : ( alloc.timeFree > zvMid ? 1 : -1 ); + int8_t val = alloc.timeFree < 0 ? + int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeAlloc ) >> 24 ) ) ) : + ( alloc.timeFree > zvMid ? + int8_t( std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeAlloc ) >> 24 ) ) ) : + int8_t( -std::max( int64_t( 1 ), 127 - ( ( zvMid - alloc.timeFree ) >> 24 ) ) ) ); const auto c0 = a0 >> ChunkBits; const auto c1 = a1 >> ChunkBits; @@ -4067,11 +4080,14 @@ Vector View::GetMemoryPages() const } else { + const auto lastTime = m_worker.GetLastTime(); for( auto& alloc : mem.data ) { const auto a0 = alloc.ptr - memlow; const auto a1 = a0 + alloc.size; - const int8_t val = alloc.timeFree < 0 ? 1 : -1; + const int8_t val = alloc.timeFree < 0 ? + int8_t( std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.timeAlloc ) ) >> 24 ) ) ) : + int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.timeFree ) ) >> 24 ) ) ); const auto c0 = a0 >> ChunkBits; const auto c1 = a1 >> ChunkBits; From c9d1f59c926d57587d6ad6462868571b2bd56de2 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 4 Apr 2018 18:53:41 +0200 Subject: [PATCH 56/58] No need to pack WelcomeMessage struct. --- common/TracyProtocol.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index 26cd611d..9afcf132 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -27,7 +27,6 @@ enum ServerQuery : uint8_t enum { WelcomeMessageProgramNameSize = 64 }; -#pragma pack( 1 ) struct WelcomeMessage { double timerMul; @@ -38,7 +37,6 @@ struct WelcomeMessage uint64_t epoch; char programName[WelcomeMessageProgramNameSize]; }; -#pragma pack() enum { WelcomeMessageSize = sizeof( WelcomeMessage ) }; From 4c76a5d66b5d537bad1160cda74417f05b8e4af7 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 4 Apr 2018 19:44:44 +0200 Subject: [PATCH 57/58] Add missing no-op macros for use if tracy is disabled. --- Tracy.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tracy.hpp b/Tracy.hpp index bfc1e81c..bde4f7f1 100644 --- a/Tracy.hpp +++ b/Tracy.hpp @@ -29,6 +29,9 @@ #define TracyMessage(x,y) #define TracyMessageL(x) +#define TracyAlloc(x,y) +#define TracyFree(x) + #else #include "client/TracyLock.hpp" From 0f95d7fd216610b994d0c6c33095787a1b5df971 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 4 Apr 2018 22:24:38 +0200 Subject: [PATCH 58/58] Use lookup table to get memory decay color. --- server/TracyView.cpp | 46 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index fd3d51dd..643e8043 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -3814,6 +3814,41 @@ enum { PageSize = 1 << PageBits }; enum { PageChunkBits = ChunkBits + PageBits }; enum { PageChunkSize = 1 << PageChunkBits }; +uint32_t MemDecayColor[256] = { + 0x0, 0xFF077F07, 0xFF078007, 0xFF078207, 0xFF078307, 0xFF078507, 0xFF078707, 0xFF078807, + 0xFF078A07, 0xFF078B07, 0xFF078D07, 0xFF078F07, 0xFF079007, 0xFF089208, 0xFF089308, 0xFF089508, + 0xFF089708, 0xFF089808, 0xFF089A08, 0xFF089B08, 0xFF089D08, 0xFF089F08, 0xFF08A008, 0xFF08A208, + 0xFF09A309, 0xFF09A509, 0xFF09A709, 0xFF09A809, 0xFF09AA09, 0xFF09AB09, 0xFF09AD09, 0xFF09AF09, + 0xFF09B009, 0xFF09B209, 0xFF09B309, 0xFF09B509, 0xFF0AB70A, 0xFF0AB80A, 0xFF0ABA0A, 0xFF0ABB0A, + 0xFF0ABD0A, 0xFF0ABF0A, 0xFF0AC00A, 0xFF0AC20A, 0xFF0AC30A, 0xFF0AC50A, 0xFF0AC70A, 0xFF0BC80B, + 0xFF0BCA0B, 0xFF0BCB0B, 0xFF0BCD0B, 0xFF0BCF0B, 0xFF0BD00B, 0xFF0BD20B, 0xFF0BD30B, 0xFF0BD50B, + 0xFF0BD70B, 0xFF0BD80B, 0xFF0BDA0B, 0xFF0CDB0C, 0xFF0CDD0C, 0xFF0CDF0C, 0xFF0CE00C, 0xFF0CE20C, + 0xFF0CE30C, 0xFF0CE50C, 0xFF0CE70C, 0xFF0CE80C, 0xFF0CEA0C, 0xFF0CEB0C, 0xFF0DED0D, 0xFF0DEF0D, + 0xFF0DF00D, 0xFF0DF20D, 0xFF0DF30D, 0xFF0DF50D, 0xFF0DF70D, 0xFF0DF80D, 0xFF0DFA0D, 0xFF0DFB0D, + 0xFF0DFD0D, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, + 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, + 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, + 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, + 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, + 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF12FF12, + 0x0, 0xFF1212FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, + 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, + 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, + 0xFF1010FF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, + 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, + 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, + 0xFF0D0DFD, 0xFF0D0DFB, 0xFF0D0DFA, 0xFF0D0DF8, 0xFF0D0DF7, 0xFF0D0DF5, 0xFF0D0DF3, 0xFF0D0DF2, + 0xFF0D0DF0, 0xFF0D0DEF, 0xFF0D0DED, 0xFF0C0CEB, 0xFF0C0CEA, 0xFF0C0CE8, 0xFF0C0CE7, 0xFF0C0CE5, + 0xFF0C0CE3, 0xFF0C0CE2, 0xFF0C0CE0, 0xFF0C0CDF, 0xFF0C0CDD, 0xFF0C0CDB, 0xFF0B0BDA, 0xFF0B0BD8, + 0xFF0B0BD7, 0xFF0B0BD5, 0xFF0B0BD3, 0xFF0B0BD2, 0xFF0B0BD0, 0xFF0B0BCF, 0xFF0B0BCD, 0xFF0B0BCB, + 0xFF0B0BCA, 0xFF0B0BC8, 0xFF0A0AC7, 0xFF0A0AC5, 0xFF0A0AC3, 0xFF0A0AC2, 0xFF0A0AC0, 0xFF0A0ABF, + 0xFF0A0ABD, 0xFF0A0ABB, 0xFF0A0ABA, 0xFF0A0AB8, 0xFF0A0AB7, 0xFF0909B5, 0xFF0909B3, 0xFF0909B2, + 0xFF0909B0, 0xFF0909AF, 0xFF0909AD, 0xFF0909AB, 0xFF0909AA, 0xFF0909A8, 0xFF0909A7, 0xFF0909A5, + 0xFF0909A3, 0xFF0808A2, 0xFF0808A0, 0xFF08089F, 0xFF08089D, 0xFF08089B, 0xFF08089A, 0xFF080898, + 0xFF080897, 0xFF080895, 0xFF080893, 0xFF080892, 0xFF070790, 0xFF07078F, 0xFF07078D, 0xFF07078B, + 0xFF07078A, 0xFF070788, 0xFF070787, 0xFF070785, 0xFF070783, 0xFF070782, 0xFF070780, 0xFF07077F, +}; + void View::DrawMemory() { auto& mem = m_worker.GetMemData(); @@ -4012,16 +4047,7 @@ void View::DrawMemory() idx++; } while( idx < PageSize && pgptr[idx] == val ); - uint32_t color; - if( val > 0 ) - { - color = 0x44FF44 | ( ( 126 + val ) << 24 ); - } - else - { - color = 0x4444FF | ( ( 126 - val ) << 24 ); - } - draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), color ); + draw->AddLine( wpos + ImVec2( i0, line ), wpos + ImVec2( idx, line ), MemDecayColor[(uint8_t)val] ); } } line++;