From fe0366c792ab7f053f3b98d60e08a279edf5ba93 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Fri, 13 Oct 2017 03:36:59 +0200 Subject: [PATCH] Receive plot data. --- client/TracyProfiler.cpp | 5 +- common/TracyProtocol.hpp | 1 + common/TracyQueue.hpp | 2 + server/TracyView.cpp | 104 +++++++++++++++++++++++++++++++++++++-- server/TracyView.hpp | 20 ++++++++ 5 files changed, 127 insertions(+), 5 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 56bb6f87..7a594420 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -193,7 +193,7 @@ bool Profiler::SendData( const char* data, size_t len ) bool Profiler::SendString( uint64_t str, const char* ptr, QueueType type ) { - assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData ); + assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData || type == QueueType::PlotName ); QueueItem item; item.hdr.type = type; @@ -264,6 +264,9 @@ bool Profiler::HandleServerQuery() case ServerQuerySourceLocation: SendSourceLocation( ptr ); break; + case ServerQueryPlotName: + SendString( ptr, (const char*)ptr, QueueType::PlotName ); + break; default: assert( false ); break; diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index bee493e7..cea9f5a6 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -22,6 +22,7 @@ enum ServerQuery : uint8_t ServerQueryThreadString, ServerQueryCustomString, ServerQuerySourceLocation, + ServerQueryPlotName, }; enum { WelcomeMessageProgramNameSize = 64 }; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 1ffa0bfc..774de925 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -22,6 +22,7 @@ enum class QueueType : uint8_t LockRelease, LockMark, PlotData, + PlotName, NUM_TYPES }; @@ -170,6 +171,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueLockRelease ), sizeof( QueueHeader ) + sizeof( QueueLockMark ), sizeof( QueueHeader ) + sizeof( QueuePlotData ), + sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // plot name }; static_assert( sizeof( QueueDataSize ) / sizeof( size_t ) == (uint8_t)QueueType::NUM_TYPES, "QueueDataSize mismatch" ); diff --git a/server/TracyView.cpp b/server/TracyView.cpp index c094d5e6..b4d27604 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -332,7 +332,7 @@ close: void View::DispatchProcess( const QueueItem& ev ) { - if( ev.hdr.type == QueueType::CustomStringData || ev.hdr.type == QueueType::StringData || ev.hdr.type == QueueType::ThreadName ) + if( ev.hdr.type == QueueType::CustomStringData || ev.hdr.type == QueueType::StringData || ev.hdr.type == QueueType::ThreadName || ev.hdr.type == QueueType::PlotName ) { timeval tv; tv.tv_sec = 0; @@ -350,10 +350,14 @@ void View::DispatchProcess( const QueueItem& ev ) { AddString( ev.stringTransfer.ptr, std::string( buf, buf+sz ) ); } - else + else if( ev.hdr.type == QueueType::ThreadName ) { AddThreadString( ev.stringTransfer.ptr, std::string( buf, buf+sz ) ); } + else + { + HandlePlotName( ev.stringTransfer.ptr, std::string( buf, buf+sz ) ); + } } else { @@ -364,7 +368,7 @@ void View::DispatchProcess( const QueueItem& ev ) void View::DispatchProcess( const QueueItem& ev, const char*& ptr ) { ptr += QueueDataSize[ev.hdr.idx]; - if( ev.hdr.type == QueueType::CustomStringData || ev.hdr.type == QueueType::StringData || ev.hdr.type == QueueType::ThreadName ) + if( ev.hdr.type == QueueType::CustomStringData || ev.hdr.type == QueueType::StringData || ev.hdr.type == QueueType::ThreadName || ev.hdr.type == QueueType::PlotName ) { uint16_t sz; memcpy( &sz, ptr, sizeof( sz ) ); @@ -377,10 +381,14 @@ void View::DispatchProcess( const QueueItem& ev, const char*& ptr ) { AddString( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) ); } - else + else if( ev.hdr.type == QueueType::ThreadName ) { AddThreadString( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) ); } + else + { + HandlePlotName( ev.stringTransfer.ptr, std::string( ptr, ptr+sz ) ); + } ptr += sz; } else @@ -432,6 +440,9 @@ void View::Process( const QueueItem& ev ) case QueueType::LockMark: ProcessLockMark( ev.lockMark ); break; + case QueueType::PlotData: + ProcessPlotData( ev.plotData ); + break; default: assert( false ); break; @@ -576,6 +587,49 @@ void View::ProcessLockMark( const QueueLockMark& ev ) } } +void View::ProcessPlotData( const QueuePlotData& ev ) +{ + PlotData* plot; + auto it = m_plotMap.find( ev.name ); + if( it == m_plotMap.end() ) + { + auto pit = m_pendingPlots.find( ev.name ); + if( pit == m_pendingPlots.end() ) + { + plot = m_slab.Alloc(); + plot->name = ev.name; + m_pendingPlots.emplace( ev.name, plot ); + ServerQuery( ServerQueryPlotName, ev.name ); + } + else + { + plot = pit->second; + } + } + else + { + plot = m_plots[it->second]; + } + + const auto time = int64_t( ev.time * m_timerMul ); + std::lock_guard lock( m_lock ); + switch( ev.type ) + { + case PlotDataType::Double: + InsertPlot( plot, time, ev.data.d ); + break; + case PlotDataType::Float: + InsertPlot( plot, time, (double)ev.data.f ); + break; + case PlotDataType::Int: + InsertPlot( plot, time, (double)ev.data.i ); + break; + default: + assert( false ); + break; + } +} + void View::CheckString( uint64_t ptr ) { if( m_strings.find( ptr ) != m_strings.end() ) return; @@ -788,6 +842,48 @@ void View::UpdateLockCount( LockMap& lockmap, size_t pos ) } } +void View::InsertPlot( PlotData* plot, int64_t time, double val ) +{ + if( plot->data.empty() || plot->data.back().time < time ) + { + plot->data.emplace_back( PlotItem { time, val } ); + } + else + { + auto it = std::lower_bound( plot->data.begin(), plot->data.end(), time, [] ( const auto& lhs, const auto& rhs ) { return lhs.time < rhs; } ); + it = plot->data.insert( it, PlotItem { time, val } ); + } +} + +void View::HandlePlotName( uint64_t name, std::string&& str ) +{ + auto pit = m_pendingPlots.find( name ); + assert( pit != m_pendingPlots.end() ); + + auto it = m_plotRev.find( str ); + if( it == m_plotRev.end() ) + { + const auto idx = m_plots.size(); + m_plots.push_back( pit->second ); + m_plotMap.emplace( name, idx ); + m_plotRev.emplace( str, idx ); + m_strings.emplace( name, std::move( str ) ); + } + else + { + m_plotMap.emplace( name, it->second ); + const auto& pp = pit->second->data; + auto plot = m_plots[it->second]; + for( auto& v : pp ) + { + InsertPlot( plot, v.time, v.val ); + } + // pit->second is leaked + } + + m_pendingPlots.erase( pit ); +} + uint64_t View::GetFrameTime( size_t idx ) const { if( idx < m_frames.size() - 1 ) diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 6322a260..271dad01 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -62,6 +62,18 @@ private: bool blocked; }; + struct PlotItem + { + int64_t time; + double val; + }; + + struct PlotData + { + uint64_t name; + std::vector data; + }; + void Worker(); void DispatchProcess( const QueueItem& ev ); @@ -79,6 +91,7 @@ private: void ProcessLockObtain( const QueueLockObtain& ev ); void ProcessLockRelease( const QueueLockRelease& ev ); void ProcessLockMark( const QueueLockMark& ev ); + void ProcessPlotData( const QueuePlotData& ev ); void CheckString( uint64_t ptr ); void CheckThreadString( uint64_t id ); @@ -98,6 +111,9 @@ private: void InsertLockEvent( LockMap& lockmap, LockEvent* lev, uint64_t thread ); void UpdateLockCount( LockMap& lockmap, size_t pos ); + void InsertPlot( PlotData* plot, int64_t time, double val ); + void HandlePlotName( uint64_t name, std::string&& str ); + uint64_t GetFrameTime( size_t idx ) const; uint64_t GetFrameBegin( size_t idx ) const; uint64_t GetFrameEnd( size_t idx ) const; @@ -145,6 +161,7 @@ private: std::mutex m_lock; Vector m_frames; Vector m_threads; + Vector m_plots; std::unordered_map m_strings; std::unordered_map m_threadNames; std::unordered_set m_customStrings; @@ -162,6 +179,9 @@ private: std::unordered_set m_pendingSourceLocation; std::unordered_map m_pendingCustomStrings; std::unordered_map m_threadMap; + std::unordered_map m_plotMap; + std::unordered_map m_plotRev; + std::unordered_map m_pendingPlots; Slab m_slab;