mirror of
https://github.com/wolfpld/tracy
synced 2025-04-29 12:23:53 +00:00
Preprocess thread context switch data.
This commit is contained in:
parent
060bab357d
commit
88f0b9c754
@ -26,6 +26,39 @@ struct TimelineDraw
|
|||||||
int num;
|
int num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class ContextSwitchDrawType : uint8_t
|
||||||
|
{
|
||||||
|
Waiting,
|
||||||
|
FoldedOne,
|
||||||
|
FoldedMulti,
|
||||||
|
Running
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContextSwitchDrawFolded
|
||||||
|
{
|
||||||
|
Int48 rend;
|
||||||
|
int num;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContextSwitchDrawWaiting
|
||||||
|
{
|
||||||
|
short_ptr<ContextSwitchData> prev;
|
||||||
|
Int24 waitStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContextSwitchDraw
|
||||||
|
{
|
||||||
|
ContextSwitchDrawType type;
|
||||||
|
short_ptr<ContextSwitchData> ev;
|
||||||
|
float minpx;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ContextSwitchDrawFolded folded;
|
||||||
|
ContextSwitchDrawWaiting waiting;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@ namespace tracy
|
|||||||
{
|
{
|
||||||
|
|
||||||
constexpr float MinVisSize = 3;
|
constexpr float MinVisSize = 3;
|
||||||
|
constexpr float MinCtxSize = 4;
|
||||||
|
|
||||||
|
|
||||||
TimelineItemThread::TimelineItemThread( View& view, Worker& worker, const ThreadData* thread )
|
TimelineItemThread::TimelineItemThread( View& view, Worker& worker, const ThreadData* thread )
|
||||||
@ -274,11 +275,13 @@ void TimelineItemThread::DrawOverlay( const ImVec2& ul, const ImVec2& dr )
|
|||||||
|
|
||||||
void TimelineItemThread::DrawFinished()
|
void TimelineItemThread::DrawFinished()
|
||||||
{
|
{
|
||||||
|
m_ctxDraw.clear();
|
||||||
m_draw.clear();
|
m_draw.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineItemThread::Preprocess( const TimelineContext& ctx, TaskDispatch& td )
|
void TimelineItemThread::Preprocess( const TimelineContext& ctx, TaskDispatch& td )
|
||||||
{
|
{
|
||||||
|
assert( m_ctxDraw.empty() );
|
||||||
assert( m_draw.empty() );
|
assert( m_draw.empty() );
|
||||||
|
|
||||||
td.Queue( [this, &ctx] {
|
td.Queue( [this, &ctx] {
|
||||||
@ -293,6 +296,17 @@ void TimelineItemThread::Preprocess( const TimelineContext& ctx, TaskDispatch& t
|
|||||||
m_depth = PreprocessZoneLevel( ctx, m_thread->timeline, 0 );
|
m_depth = PreprocessZoneLevel( ctx, m_thread->timeline, 0 );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
if( m_view.GetViewData().drawContextSwitches )
|
||||||
|
{
|
||||||
|
auto ctxSwitch = m_worker.GetContextSwitchData( m_thread->id );
|
||||||
|
if( ctxSwitch )
|
||||||
|
{
|
||||||
|
td.Queue( [this, &ctx, ctxSwitch] {
|
||||||
|
PreprocessContextSwitches( ctx, *ctxSwitch );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TRACY_NO_STATISTICS
|
#ifndef TRACY_NO_STATISTICS
|
||||||
@ -431,4 +445,97 @@ int TimelineItemThread::PreprocessZoneLevel( const TimelineContext& ctx, const V
|
|||||||
return maxdepth;
|
return maxdepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TimelineItemThread::PreprocessContextSwitches( const TimelineContext& ctx, const ContextSwitch& ctxSwitch )
|
||||||
|
{
|
||||||
|
const auto w = ctx.w;
|
||||||
|
const auto pxns = ctx.pxns;
|
||||||
|
const auto nspx = ctx.nspx;
|
||||||
|
const auto vStart = ctx.vStart;
|
||||||
|
const auto vEnd = ctx.vEnd;
|
||||||
|
|
||||||
|
auto& vec = ctxSwitch.v;
|
||||||
|
auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, vStart ), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||||
|
if( it == vec.end() ) return;
|
||||||
|
if( it != vec.begin() ) --it;
|
||||||
|
|
||||||
|
auto citend = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
||||||
|
if( it == citend ) return;
|
||||||
|
if( citend != vec.end() ) ++citend;
|
||||||
|
|
||||||
|
const auto MinCtxNs = MinCtxSize * nspx;
|
||||||
|
const auto& sampleData = m_thread->samples;
|
||||||
|
|
||||||
|
auto pit = citend;
|
||||||
|
double minpx = -10.0;
|
||||||
|
while( it < citend )
|
||||||
|
{
|
||||||
|
auto& ev = *it;
|
||||||
|
if( pit != citend )
|
||||||
|
{
|
||||||
|
Int24 waitStack;
|
||||||
|
if( !sampleData.empty() )
|
||||||
|
{
|
||||||
|
auto sdit = std::lower_bound( sampleData.begin(), sampleData.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
||||||
|
bool found = sdit != sampleData.end() && sdit->time.Val() == ev.Start();
|
||||||
|
if( !found && it != vec.begin() )
|
||||||
|
{
|
||||||
|
auto eit = it;
|
||||||
|
--eit;
|
||||||
|
sdit = std::lower_bound( sampleData.begin(), sampleData.end(), eit->End(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
||||||
|
found = sdit != sampleData.end() && sdit->time.Val() == eit->End();
|
||||||
|
}
|
||||||
|
if( found ) waitStack = sdit->callstack;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Waiting, &ev, float( minpx ) } );
|
||||||
|
ref.waiting.prev = pit;
|
||||||
|
ref.waiting.waitStack = waitStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime();
|
||||||
|
const auto zsz = std::max( ( end - ev.Start() ) * pxns, pxns * 0.5 );
|
||||||
|
if( zsz < MinCtxSize )
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
const auto px0 = std::max( ( ev.Start() - vStart ) * pxns, -10.0 );
|
||||||
|
auto px1ns = end - vStart;
|
||||||
|
auto rend = end;
|
||||||
|
auto nextTime = end + MinCtxNs;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
const auto prevIt = it;
|
||||||
|
it = std::lower_bound( it, citend, nextTime, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||||
|
if( it == prevIt ) ++it;
|
||||||
|
num += std::distance( prevIt, it );
|
||||||
|
if( it == citend ) break;
|
||||||
|
const auto nend = it->IsEndValid() ? it->End() : m_worker.GetLastTime();
|
||||||
|
const auto nsnext = nend - vStart;
|
||||||
|
if( nsnext - px1ns >= MinCtxNs * 2 ) break;
|
||||||
|
px1ns = nsnext;
|
||||||
|
rend = nend;
|
||||||
|
nextTime = nend + nspx;
|
||||||
|
}
|
||||||
|
minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) );
|
||||||
|
if( num == 1 )
|
||||||
|
{
|
||||||
|
auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::FoldedOne, &ev, float( minpx ) } );
|
||||||
|
ref.folded.rend = rend;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::FoldedMulti, &ev, float( minpx ) } );
|
||||||
|
ref.folded.rend = rend;
|
||||||
|
ref.folded.num = num;
|
||||||
|
}
|
||||||
|
pit = it-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Running, &ev, float( minpx ) } );
|
||||||
|
pit = it;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,12 @@ private:
|
|||||||
template<typename Adapter, typename V>
|
template<typename Adapter, typename V>
|
||||||
int PreprocessZoneLevel( const TimelineContext& ctx, const V& vec, int depth );
|
int PreprocessZoneLevel( const TimelineContext& ctx, const V& vec, int depth );
|
||||||
|
|
||||||
|
void PreprocessContextSwitches( const TimelineContext& ctx, const ContextSwitch& ctxSwitch );
|
||||||
|
|
||||||
const ThreadData* m_thread;
|
const ThreadData* m_thread;
|
||||||
bool m_ghost;
|
bool m_ghost;
|
||||||
|
|
||||||
|
std::vector<ContextSwitchDraw> m_ctxDraw;
|
||||||
std::vector<TimelineDraw> m_draw;
|
std::vector<TimelineDraw> m_draw;
|
||||||
int m_depth;
|
int m_depth;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user