Fix CPU profiler events extraction when buffer is full

This commit is contained in:
Wojtek Figat
2023-05-08 17:05:40 +02:00
parent 959fa185c3
commit ec6e459aa7
4 changed files with 55 additions and 46 deletions

View File

@@ -197,7 +197,7 @@ namespace FlaxEditor.Windows.Profiler
if (_tableRowsCache == null)
_tableRowsCache = new List<Row>();
var viewRange = GetEventsViewRange();
var viewRange = _showOnlyLastUpdateEvents ? GetMainThreadUpdateRange() : ViewRange.Full;
UpdateTimeline(ref viewRange);
UpdateTable(ref viewRange);
}
@@ -235,36 +235,27 @@ namespace FlaxEditor.Windows.Profiler
}
}
private ViewRange GetEventsViewRange()
private ViewRange GetMainThreadUpdateRange()
{
if (_showOnlyLastUpdateEvents)
if (_events != null && _events.Count != 0)
{
// Find root event named 'Update' and use it as a view range
if (_events != null && _events.Count != 0)
var threads = _events.Get(_mainChart.SelectedSampleIndex);
if (threads != null)
{
var data = _events.Get(_mainChart.SelectedSampleIndex);
if (data != null)
for (int j = 0; j < threads.Length; j++)
{
for (int j = 0; j < data.Length; j++)
var thread = threads[j];
if (thread.Name != "Main" || thread.Events == null)
continue;
for (int i = 0; i < thread.Events.Length; i++)
{
var events = data[j].Events;
if (events == null)
continue;
for (int i = 0; i < events.Length; i++)
{
var e = events[i];
if (e.Depth == 0 && e.Name == "Update")
{
return new ViewRange(ref e);
}
}
ref var e = ref thread.Events[i];
if (e.Depth == 0 && e.Name == "Update")
return new ViewRange(ref e);
}
}
}
}
return ViewRange.Full;
}
@@ -352,13 +343,28 @@ namespace FlaxEditor.Windows.Profiler
// Find the first event start time (for the timeline start time)
double startTime = double.MaxValue;
for (int i = 0; i < data.Length; i++)
if (viewRange.Start > 0)
{
if (data[i].Events != null && data[i].Events.Length != 0)
startTime = Math.Min(startTime, data[i].Events[0].Start);
startTime = viewRange.Start;
}
else
{
var r = GetMainThreadUpdateRange();
if (r.Start > 0)
{
startTime = r.Start;
}
else
{
for (int i = 0; i < data.Length; i++)
{
if (data[i].Events != null && data[i].Events.Length != 0)
startTime = Math.Min(startTime, data[i].Events[0].Start);
}
if (startTime >= double.MaxValue)
return 0;
}
}
if (startTime >= double.MaxValue)
return 0;
var container = _timeline.EventsContainer;

View File

@@ -24,7 +24,7 @@ ProfilerCPU::EventBuffer::~EventBuffer()
DeleteArray(_data, _capacity);
}
void ProfilerCPU::EventBuffer::Extract(Array<Event>& data, bool withRemove)
void ProfilerCPU::EventBuffer::Extract(Array<Event>& data, bool withRemoval)
{
data.Clear();
@@ -36,6 +36,13 @@ void ProfilerCPU::EventBuffer::Extract(Array<Event>& data, bool withRemove)
if (count == 0)
return;
// Fix iterators when buffer is full (begin == end)
if (count == capacity)
{
_count--;
count--;
}
// Find the first item (skip non-root events)
Iterator firstEvent = Begin();
for (auto i = firstEvent; i.IsNotEnd(); ++i)
@@ -55,7 +62,7 @@ void ProfilerCPU::EventBuffer::Extract(Array<Event>& data, bool withRemove)
Iterator lastEndedRoot = End();
for (auto i = Last(); i != firstEvent; --i)
{
if (i.Event().Depth == 0 && i.Event().End != 0)
if (i.Event().Depth == 0 && i.Event().End > 0)
{
lastEndedRoot = i;
break;
@@ -71,31 +78,27 @@ void ProfilerCPU::EventBuffer::Extract(Array<Event>& data, bool withRemove)
const double lastRootEventEndTime = lastEndedRoot.Event().End;
for (auto i = --End(); i != lastEndedRoot; --i)
{
if (i.Event().End != 0 && i.Event().End <= lastRootEventEndTime)
if (i.Event().End > 0 && i.Event().End <= lastRootEventEndTime)
{
lastEvent = i;
break;
}
}
if (withRemove)
if (withRemoval)
{
// Remove all the events between [Begin(), lastEvent]
_count -= (lastEvent.Index() - Begin().Index()) & _capacityMask;
}
// Extract all the events between [firstEvent, lastEvent]
const int32 head = (lastEvent.Index() + 1) & _capacityMask;
count = (lastEvent.Index() - firstEvent.Index() + 1) & _capacityMask;
data.Resize(count, false);
int32 tail = (head - count) & _capacityMask;
int32 spaceLeft = capacity - tail;
int32 spaceLeftCount = Math::Min(spaceLeft, count);
int32 overflow = count - spaceLeft;
const int32 tail = (head - count) & _capacityMask;
const int32 spaceLeft = capacity - tail;
const int32 spaceLeftCount = Math::Min(spaceLeft, count);
const int32 overflow = count - spaceLeft;
Platform::MemoryCopy(data.Get(), &_data[tail], spaceLeftCount * sizeof(Event));
if (overflow > 0)
Platform::MemoryCopy(data.Get() + spaceLeftCount, &_data[0], overflow * sizeof(Event));

View File

@@ -106,8 +106,8 @@ public:
/// Extracts the buffer data (only ended events starting from the root level with depth=0).
/// </summary>
/// <param name="data">The output data.</param>
/// <param name="withRemove">True if also remove extracted events to prevent double-gather, false if don't modify the buffer data.</param>
void Extract(Array<Event, HeapAllocation>& data, bool withRemove);
/// <param name="withRemoval">True if also remove extracted events to prevent double-gather, false if don't modify the buffer data.</param>
void Extract(Array<Event, HeapAllocation>& data, bool withRemoval);
public:
/// <summary>

View File

@@ -57,13 +57,13 @@ void ProfilingToolsService::Update()
ProfilingTools::EventsCPU.EnsureCapacity(threads.Count());
for (int32 i = 0; i < threads.Count(); i++)
{
auto t = threads[i];
if (t == nullptr)
ProfilerCPU::Thread* thread = threads[i];
if (thread == nullptr)
continue;
ProfilingTools::ThreadStats* pt = nullptr;
for (auto& e : ProfilingTools::EventsCPU)
{
if (e.Name == t->GetName())
if (e.Name == thread->GetName())
{
pt = &e;
break;
@@ -72,10 +72,10 @@ void ProfilingToolsService::Update()
if (!pt)
{
pt = &ProfilingTools::EventsCPU.AddOne();
pt->Name = t->GetName();
pt->Name = thread->GetName();
}
t->Buffer.Extract(pt->Events, true);
thread->Buffer.Extract(pt->Events, true);
}
#if 0