Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Taudul <wolf@nereid.pl>2022-09-04 00:28:54 +0300
committerBartosz Taudul <wolf@nereid.pl>2022-09-04 00:28:54 +0300
commitec3dcaeef38f0ec909e93626d4ff6dea0213be58 (patch)
tree29b1a6aa394b53bc93110e7c7b1d236c9ec2818f /server/TracyTimelineItemThread.cpp
parente3007062fcfe81ac3c121bcea7bc6ed87e5eb299 (diff)
Migrate drawing CPU threads to the new timeline item system.
Diffstat (limited to 'server/TracyTimelineItemThread.cpp')
-rw-r--r--server/TracyTimelineItemThread.cpp266
1 files changed, 266 insertions, 0 deletions
diff --git a/server/TracyTimelineItemThread.cpp b/server/TracyTimelineItemThread.cpp
new file mode 100644
index 00000000..7b515107
--- /dev/null
+++ b/server/TracyTimelineItemThread.cpp
@@ -0,0 +1,266 @@
+#include <algorithm>
+#include <limits>
+
+#include "TracyImGui.hpp"
+#include "TracyMouse.hpp"
+#include "TracyPrint.hpp"
+#include "TracyTimelineItemThread.hpp"
+#include "TracyView.hpp"
+#include "TracyWorker.hpp"
+
+namespace tracy
+{
+
+TimelineItemThread::TimelineItemThread( View& view, Worker& worker, const ThreadData* thread )
+ : TimelineItem( view, worker )
+ , m_thread( thread )
+ , m_ghost( false )
+{
+}
+
+bool TimelineItemThread::IsEmpty() const
+{
+ auto& crash = m_worker.GetCrashEvent();
+ return crash.thread != m_thread->id &&
+ m_thread->timeline.empty() &&
+ m_thread->messages.empty() &&
+ m_thread->ghostZones.empty();
+}
+
+uint32_t TimelineItemThread::HeaderColor() const
+{
+ auto& crash = m_worker.GetCrashEvent();
+ if( crash.thread == m_thread->id ) return 0xFF2222FF;
+ if( m_thread->isFiber ) return 0xFF88FF88;
+ return 0xFFFFFFFF;
+}
+
+uint32_t TimelineItemThread::HeaderColorInactive() const
+{
+ auto& crash = m_worker.GetCrashEvent();
+ if( crash.thread == m_thread->id ) return 0xFF111188;
+ if( m_thread->isFiber ) return 0xFF448844;
+ return 0xFF888888;
+}
+
+uint32_t TimelineItemThread::HeaderLineColor() const
+{
+ return 0x33FFFFFF;
+}
+
+const char* TimelineItemThread::HeaderLabel() const
+{
+ return m_worker.GetThreadName( m_thread->id );
+}
+
+int64_t TimelineItemThread::RangeBegin() const
+{
+ int64_t first = std::numeric_limits<int64_t>::max();
+ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );
+ if( ctx && !ctx->v.empty() )
+ {
+ first = ctx->v.begin()->Start();
+ }
+ if( !m_thread->timeline.empty() )
+ {
+ if( m_thread->timeline.is_magic() )
+ {
+ auto& tl = *((Vector<ZoneEvent>*)&m_thread->timeline);
+ first = std::min( first, tl.front().Start() );
+ }
+ else
+ {
+ first = std::min( first, m_thread->timeline.front()->Start() );
+ }
+ }
+ if( !m_thread->messages.empty() )
+ {
+ first = std::min( first, m_thread->messages.front()->time );
+ }
+ for( const auto& lock : m_worker.GetLockMap() )
+ {
+ const auto& lockmap = *lock.second;
+ if( !lockmap.valid ) continue;
+ auto it = lockmap.threadMap.find( m_thread->id );
+ if( it == lockmap.threadMap.end() ) continue;
+ const auto thread = it->second;
+ auto lptr = lockmap.timeline.data();
+ while( lptr->ptr->thread != thread ) lptr++;
+ if( lptr->ptr->Time() < first ) first = lptr->ptr->Time();
+ }
+ return first;
+}
+
+int64_t TimelineItemThread::RangeEnd() const
+{
+ int64_t last = -1;
+ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );
+ if( ctx && !ctx->v.empty() )
+ {
+ const auto& back = ctx->v.back();
+ last = back.IsEndValid() ? back.End() : back.Start();
+ }
+ if( !m_thread->timeline.empty() )
+ {
+ if( m_thread->timeline.is_magic() )
+ {
+ auto& tl = *((Vector<ZoneEvent>*)&m_thread->timeline);
+ last = std::max( last, m_worker.GetZoneEnd( tl.back() ) );
+ }
+ else
+ {
+ last = std::max( last, m_worker.GetZoneEnd( *m_thread->timeline.back() ) );
+ }
+ }
+ if( !m_thread->messages.empty() )
+ {
+ last = std::max( last, m_thread->messages.back()->time );
+ }
+ for( const auto& lock : m_worker.GetLockMap() )
+ {
+ const auto& lockmap = *lock.second;
+ if( !lockmap.valid ) continue;
+ auto it = lockmap.threadMap.find( m_thread->id );
+ if( it == lockmap.threadMap.end() ) continue;
+ const auto thread = it->second;
+ auto eptr = lockmap.timeline.data() + lockmap.timeline.size() - 1;
+ while( eptr->ptr->thread != thread ) eptr--;
+ if( eptr->ptr->Time() > last ) last = eptr->ptr->Time();
+ }
+ return last;
+}
+
+void TimelineItemThread::HeaderTooltip( const char* label ) const
+{
+ m_view.HighlightThread( m_thread->id );
+
+ ImGui::BeginTooltip();
+ SmallColorBox( GetThreadColor( m_thread->id, 0, m_view.GetViewData().dynamicColors ) );
+ ImGui::SameLine();
+ ImGui::TextUnformatted( m_worker.GetThreadName( m_thread->id ) );
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%s)", RealToString( m_thread->id ) );
+ auto& crash = m_worker.GetCrashEvent();
+ if( crash.thread == m_thread->id )
+ {
+ ImGui::SameLine();
+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );
+ }
+ if( m_thread->isFiber )
+ {
+ ImGui::SameLine();
+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );
+ }
+
+ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );
+ const auto first = RangeBegin();
+ const auto last = RangeEnd();
+
+ ImGui::Separator();
+
+ size_t lockCnt = 0;
+ for( const auto& lock : m_worker.GetLockMap() )
+ {
+ const auto& lockmap = *lock.second;
+ if( !lockmap.valid ) continue;
+ auto it = lockmap.threadMap.find( m_thread->id );
+ if( it == lockmap.threadMap.end() ) continue;
+ lockCnt++;
+ }
+
+ if( last >= 0 )
+ {
+ const auto lifetime = last - first;
+ const auto traceLen = m_worker.GetLastTime();
+
+ TextFocused( "Appeared at", TimeToString( first ) );
+ TextFocused( "Last event at", TimeToString( last ) );
+ TextFocused( "Lifetime:", TimeToString( lifetime ) );
+ ImGui::SameLine();
+ char buf[64];
+ PrintStringPercent( buf, lifetime / double( traceLen ) * 100 );
+ TextDisabledUnformatted( buf );
+
+ if( ctx )
+ {
+ TextFocused( "Time in running state:", TimeToString( ctx->runningTime ) );
+ ImGui::SameLine();
+ PrintStringPercent( buf, ctx->runningTime / double( lifetime ) * 100 );
+ TextDisabledUnformatted( buf );
+ }
+ }
+
+ ImGui::Separator();
+ if( !m_thread->timeline.empty() )
+ {
+ TextFocused( "Zone count:", RealToString( m_thread->count ) );
+ TextFocused( "Top-level zones:", RealToString( m_thread->timeline.size() ) );
+ }
+ if( !m_thread->messages.empty() )
+ {
+ TextFocused( "Messages:", RealToString( m_thread->messages.size() ) );
+ }
+ if( lockCnt != 0 )
+ {
+ TextFocused( "Locks:", RealToString( lockCnt ) );
+ }
+ if( ctx )
+ {
+ TextFocused( "Running state regions:", RealToString( ctx->v.size() ) );
+ }
+ if( !m_thread->samples.empty() )
+ {
+ TextFocused( "Call stack samples:", RealToString( m_thread->samples.size() ) );
+ if( m_thread->kernelSampleCnt != 0 )
+ {
+ TextFocused( "Kernel samples:", RealToString( m_thread->kernelSampleCnt ) );
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%.2f%%)", 100.f * m_thread->kernelSampleCnt / m_thread->samples.size() );
+ }
+ }
+ ImGui::EndTooltip();
+}
+
+void TimelineItemThread::HeaderExtraContents( int offset, const ImVec2& wpos, float labelWidth, double pxns, bool hover )
+{
+ m_view.DrawThreadMessages( *m_thread, pxns, offset, wpos, hover );
+
+#ifndef TRACY_NO_STATISTICS
+ const bool hasGhostZones = m_worker.AreGhostZonesReady() && !m_thread->ghostZones.empty();
+ if( hasGhostZones && !m_thread->timeline.empty() )
+ {
+ auto draw = ImGui::GetWindowDrawList();
+ const auto ty = ImGui::GetTextLineHeight();
+
+ const auto color = m_ghost ? 0xFFAA9999 : 0x88AA7777;
+ draw->AddText( wpos + ImVec2( 1.5f * ty + labelWidth, offset ), color, ICON_FA_GHOST );
+ float ghostSz = ImGui::CalcTextSize( ICON_FA_GHOST ).x;
+
+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 1.5f * ty + labelWidth, offset ), wpos + ImVec2( 1.5f * ty + labelWidth + ghostSz, offset + ty ) ) )
+ {
+ if( IsMouseClicked( 0 ) )
+ {
+ m_ghost = !m_ghost;
+ }
+ }
+ }
+#endif
+}
+
+bool TimelineItemThread::DrawContents( double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax )
+{
+ const auto res = m_view.DrawThread( *m_thread, pxns, offset, wpos, hover, yMin, yMax, m_ghost );
+ if( !res )
+ {
+ auto& crash = m_worker.GetCrashEvent();
+ return crash.thread == m_thread->id;
+ }
+ return true;
+}
+
+void TimelineItemThread::DrawOverlay( const ImVec2& ul, const ImVec2& dr )
+{
+ m_view.DrawThreadOverlays( *m_thread, ul, dr );
+}
+
+}