mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-27 00:04:35 +00:00
Apply group filters to the samples statistics in the "find zone" window
reduce memory by storing the thread ids next to the zones intead of making zone lists per thread. speed-up by reading the zones in linear order rather than bisecting the whole list for each sample.
This commit is contained in:
parent
41130d2a69
commit
63acfe72e7
@ -10721,42 +10721,41 @@ void View::DrawFindZone()
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if( ImGui::Checkbox( ICON_FA_HAT_WIZARD " Include kernel", &m_statShowKernel ))
|
if( ImGui::Checkbox( ICON_FA_HAT_WIZARD " Include kernel", &m_statShowKernel ))
|
||||||
{
|
{
|
||||||
m_findZone.samplesCache.scheduleUpdate = true;
|
m_findZone.samples.scheduleUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_findZone.samplesCache.needZonesPerThread )
|
if( !m_findZone.samples.enabled )
|
||||||
{
|
{
|
||||||
m_findZone.samplesCache.needZonesPerThread = true;
|
m_findZone.samples.enabled = true;
|
||||||
|
m_findZone.samples.scheduleUpdate = true;
|
||||||
m_findZone.scheduleResetMatch = true;
|
m_findZone.scheduleResetMatch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_findZone.samplesCache.scheduleUpdate && !m_findZone.scheduleResetMatch )
|
if( m_findZone.samples.enabled && m_findZone.samples.scheduleUpdate && !m_findZone.scheduleResetMatch )
|
||||||
{
|
{
|
||||||
m_findZone.samplesCache.scheduleUpdate = false;
|
m_findZone.samples.scheduleUpdate = false;
|
||||||
|
|
||||||
m_findZone.samplesCache.timeRange = 0;
|
|
||||||
for( auto& t: m_findZone.samplesCache.threads )
|
|
||||||
{
|
|
||||||
pdqsort_branchless( t.second.begin(), t.second.end(), []( const auto& lhs, const auto& rhs ) { return (*lhs).Start() < (*rhs).Start(); } );
|
|
||||||
|
|
||||||
int64_t prevEnd = 0;
|
|
||||||
for( const auto& it : t.second )
|
|
||||||
{
|
|
||||||
int64_t start = (*it).Start();
|
|
||||||
int64_t end = (*it).End();
|
|
||||||
if( start < prevEnd ) start = prevEnd;
|
|
||||||
if( start < end )
|
|
||||||
{
|
|
||||||
prevEnd = end;
|
|
||||||
m_findZone.samplesCache.timeRange += end - start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& symMap = m_worker.GetSymbolMap();
|
const auto& symMap = m_worker.GetSymbolMap();
|
||||||
m_findZone.samplesCache.counts.clear();
|
m_findZone.samples.counts.clear();
|
||||||
m_findZone.samplesCache.counts.reserve( symMap.size() );
|
m_findZone.samples.counts.reserve( symMap.size() );
|
||||||
|
|
||||||
|
struct GroupRange {
|
||||||
|
const FindZone::Group* group;
|
||||||
|
Vector<short_ptr<ZoneEvent>>::const_iterator begin;
|
||||||
|
Vector<short_ptr<ZoneEvent>>::const_iterator end;
|
||||||
|
};
|
||||||
|
Vector<GroupRange> selectedGroups;
|
||||||
|
selectedGroups.reserve( m_findZone.groups.size() );
|
||||||
|
for( auto it = m_findZone.groups.begin(); it != m_findZone.groups.end(); ++it )
|
||||||
|
{
|
||||||
|
assert( it->second.zones.size() == it->second.zonesTids.size() );
|
||||||
|
if( ( m_findZone.selGroup == m_findZone.Unselected || it->first == m_findZone.selGroup )
|
||||||
|
&& !it->second.zones.empty() )
|
||||||
|
{
|
||||||
|
selectedGroups.push_back_no_space_check( GroupRange{&it->second} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for( auto& v : symMap )
|
for( auto& v : symMap )
|
||||||
{
|
{
|
||||||
@ -10777,37 +10776,81 @@ void View::DrawFindZone()
|
|||||||
|
|
||||||
auto samples = m_worker.GetSamplesForSymbol( v.first );
|
auto samples = m_worker.GetSamplesForSymbol( v.first );
|
||||||
if( !samples ) continue;
|
if( !samples ) continue;
|
||||||
|
if( samples->empty() ) continue;
|
||||||
|
|
||||||
|
auto samplesBegin = samples->begin();
|
||||||
|
auto samplesEnd = samples->end();
|
||||||
|
if( m_findZone.range.active )
|
||||||
|
{
|
||||||
|
const auto rangeMin = m_findZone.range.min;
|
||||||
|
const auto rangeMax = m_findZone.range.max;
|
||||||
|
samplesBegin = std::lower_bound( samplesBegin, samplesEnd, rangeMin, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );
|
||||||
|
if( samplesBegin != samplesEnd )
|
||||||
|
{
|
||||||
|
samplesEnd = std::lower_bound( samplesBegin, samplesEnd, rangeMax, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( samplesBegin == samplesEnd ) continue;
|
||||||
|
|
||||||
|
bool empty = true;
|
||||||
|
const auto firstTime = samplesBegin->time.Val();
|
||||||
|
const auto lastTime = samplesEnd->time.Val();
|
||||||
|
for( auto& g: selectedGroups )
|
||||||
|
{
|
||||||
|
const auto& zones = g.group->zones;
|
||||||
|
auto begin = std::lower_bound( zones.begin(), zones.end(), firstTime, [] ( const auto& l, const auto& r ) { return l->Start() < r; } );
|
||||||
|
auto end = std::upper_bound( begin, zones.end(), lastTime, [] ( const auto& l, const auto& r ) { return l <= r->Start(); } );
|
||||||
|
g.begin = begin;
|
||||||
|
g.end = end;
|
||||||
|
empty = empty && (begin == end);
|
||||||
|
}
|
||||||
|
if (empty) continue;
|
||||||
|
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
for( auto it: *samples )
|
for( auto it = samplesBegin; it != samplesEnd; ++it )
|
||||||
{
|
{
|
||||||
const auto time = it.time.Val();
|
const auto time = it->time.Val();
|
||||||
const auto& zones = m_findZone.samplesCache.threads[it.thread];
|
bool pass = false;
|
||||||
auto z = std::lower_bound( zones.begin(), zones.end(), time, [] ( const auto& l, const auto& r ) { return l->Start() < r; } );
|
for( auto& g: selectedGroups )
|
||||||
if( z == zones.end() ) continue;
|
{
|
||||||
if( z != zones.begin() ) --z;
|
while( g.begin != g.end && time > (*g.begin)->End() ) ++g.begin;
|
||||||
if( time >= (*z)->Start() && time < (*z)->End() )
|
if( g.begin == g.end ) continue;
|
||||||
count++;
|
if( time < (*g.begin)->Start() ) continue;
|
||||||
|
|
||||||
|
const auto& tids = g.group->zonesTids;
|
||||||
|
const auto firstZone = g.group->zones.begin();
|
||||||
|
for (auto z = g.begin; z != g.end && (*z)->Start() <= time; ++z)
|
||||||
|
{
|
||||||
|
auto zoneIndex = z - firstZone;
|
||||||
|
if( (*z)->End() > time && it->thread == tids[zoneIndex] )
|
||||||
|
{
|
||||||
|
pass = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( pass ) count ++;
|
||||||
}
|
}
|
||||||
if( count > 0 ) m_findZone.samplesCache.counts.push_back_no_space_check( SymList { v.first, 0, count } );
|
if( count > 0 ) m_findZone.samples.counts.push_back_no_space_check( SymList { v.first, 0, count } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<SymList> data;
|
Vector<SymList> data;
|
||||||
data.reserve( m_findZone.samplesCache.counts.size() );
|
data.reserve( m_findZone.samples.counts.size() );
|
||||||
for( auto it: m_findZone.samplesCache.counts ) data.push_back_no_space_check( it );
|
for( auto it: m_findZone.samples.counts ) data.push_back_no_space_check( it );
|
||||||
DrawSamplesStatistics( data, m_findZone.samplesCache.timeRange, AccumulationMode::SelfOnly );
|
int64_t timeRange = ( m_findZone.selGroup != m_findZone.Unselected ) ? m_findZone.selTotal : m_findZone.total;
|
||||||
|
DrawSamplesStatistics( data, timeRange, AccumulationMode::SelfOnly );
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( m_findZone.samplesCache.needZonesPerThread )
|
if( m_findZone.samples.enabled )
|
||||||
{
|
{
|
||||||
m_findZone.samplesCache.needZonesPerThread = false;
|
m_findZone.samples.enabled = false;
|
||||||
m_findZone.samplesCache.scheduleUpdate = false;
|
m_findZone.samples.scheduleUpdate = false;
|
||||||
m_findZone.samplesCache.counts = Vector<SymList>();
|
m_findZone.samples.counts = Vector<SymList>();
|
||||||
m_findZone.samplesCache.threads = unordered_flat_map<uint16_t, Vector<short_ptr<ZoneEvent>> >();
|
for( auto& it: m_findZone.groups ) it.second.zonesTids.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
@ -10866,9 +10909,8 @@ void View::DrawFindZone()
|
|||||||
const auto highlightActive = m_findZone.highlight.active;
|
const auto highlightActive = m_findZone.highlight.active;
|
||||||
const auto limitRange = m_findZone.range.active;
|
const auto limitRange = m_findZone.range.active;
|
||||||
FindZone::Group* group = nullptr;
|
FindZone::Group* group = nullptr;
|
||||||
uint64_t lastGid = std::numeric_limits<uint64_t>::max() - 1;
|
const uint64_t invalidGid = std::numeric_limits<uint64_t>::max() - 1;
|
||||||
Vector<short_ptr<ZoneEvent>>* threadZones = nullptr;
|
uint64_t lastGid = invalidGid;
|
||||||
uint16_t lastTid = std::numeric_limits<uint16_t>::max();
|
|
||||||
auto zptr = zones.data() + m_findZone.processed;
|
auto zptr = zones.data() + m_findZone.processed;
|
||||||
const auto zend = zones.data() + zones.size();
|
const auto zend = zones.data() + zones.size();
|
||||||
while( zptr < zend )
|
while( zptr < zend )
|
||||||
@ -10964,27 +11006,25 @@ void View::DrawFindZone()
|
|||||||
{
|
{
|
||||||
it = m_findZone.groups.emplace( gid, FindZone::Group { m_findZone.groupId++ } ).first;
|
it = m_findZone.groups.emplace( gid, FindZone::Group { m_findZone.groupId++ } ).first;
|
||||||
it->second.zones.reserve( 1024 );
|
it->second.zones.reserve( 1024 );
|
||||||
|
if( m_findZone.samples.enabled )
|
||||||
|
it->second.zonesTids.reserve( 1024 );
|
||||||
}
|
}
|
||||||
group = &it->second;
|
group = &it->second;
|
||||||
}
|
}
|
||||||
group->time += timespan;
|
group->time += timespan;
|
||||||
group->zones.push_back_non_empty( ev.Zone() );
|
group->zones.push_back_non_empty( ev.Zone() );
|
||||||
|
if( m_findZone.samples.enabled )
|
||||||
|
group->zonesTids.push_back_non_empty( ev.Thread() );
|
||||||
if( m_findZone.samplesCache.needZonesPerThread )
|
|
||||||
{
|
|
||||||
if( lastTid != ev.Thread() )
|
|
||||||
{
|
|
||||||
lastTid = ev.Thread();
|
|
||||||
threadZones = &m_findZone.samplesCache.threads[lastTid];
|
|
||||||
threadZones->reserve( 1024 );
|
|
||||||
}
|
|
||||||
threadZones->push_back_non_empty( ev.Zone() );
|
|
||||||
m_findZone.samplesCache.scheduleUpdate = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_findZone.processed = zptr - zones.data();
|
m_findZone.processed = zptr - zones.data();
|
||||||
|
|
||||||
|
const bool groupsUpdated = lastGid != invalidGid;
|
||||||
|
if( m_findZone.samples.enabled && groupsUpdated )
|
||||||
|
{
|
||||||
|
m_findZone.samples.scheduleUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector<decltype( m_findZone.groups )::iterator> groups;
|
Vector<decltype( m_findZone.groups )::iterator> groups;
|
||||||
groups.reserve_and_use( m_findZone.groups.size() );
|
groups.reserve_and_use( m_findZone.groups.size() );
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
@ -516,6 +516,7 @@ private:
|
|||||||
{
|
{
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
Vector<short_ptr<ZoneEvent>> zones;
|
Vector<short_ptr<ZoneEvent>> zones;
|
||||||
|
Vector<uint16_t> zonesTids;
|
||||||
int64_t time = 0;
|
int64_t time = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -563,12 +564,10 @@ private:
|
|||||||
} binCache;
|
} binCache;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unordered_flat_map<uint16_t, Vector<short_ptr<ZoneEvent>> > threads;
|
|
||||||
Vector<SymList> counts;
|
Vector<SymList> counts;
|
||||||
int64_t timeRange = 0;
|
|
||||||
bool scheduleUpdate = false;
|
bool scheduleUpdate = false;
|
||||||
bool needZonesPerThread = false;
|
bool enabled = false;
|
||||||
} samplesCache;
|
} samples;
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
@ -595,8 +594,6 @@ private:
|
|||||||
{
|
{
|
||||||
ResetSelection();
|
ResetSelection();
|
||||||
groups.clear();
|
groups.clear();
|
||||||
samplesCache.threads.clear();
|
|
||||||
samplesCache.counts.clear();
|
|
||||||
processed = 0;
|
processed = 0;
|
||||||
groupId = 0;
|
groupId = 0;
|
||||||
selCs = 0;
|
selCs = 0;
|
||||||
@ -613,6 +610,8 @@ private:
|
|||||||
selTotal = 0;
|
selTotal = 0;
|
||||||
selTime = 0;
|
selTime = 0;
|
||||||
binCache.numBins = -1;
|
binCache.numBins = -1;
|
||||||
|
samples.counts.clear();
|
||||||
|
samples.scheduleUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowZone( int16_t srcloc, const char* name )
|
void ShowZone( int16_t srcloc, const char* name )
|
||||||
|
Loading…
Reference in New Issue
Block a user