Add pooling for timeline event controls in profiler
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
@@ -50,7 +51,9 @@ namespace FlaxEditor.Windows.Profiler
|
||||
private readonly SingleChart _mainChart;
|
||||
private readonly Timeline _timeline;
|
||||
private readonly Table _table;
|
||||
private readonly SamplesBuffer<ProfilingTools.ThreadStats[]> _events = new SamplesBuffer<ProfilingTools.ThreadStats[]>();
|
||||
private SamplesBuffer<ProfilingTools.ThreadStats[]> _events;
|
||||
private List<Timeline.TrackLabel> _timelineLabelsCache;
|
||||
private List<Timeline.Event> _timelineEventsCache;
|
||||
private bool _showOnlyLastUpdateEvents;
|
||||
|
||||
public CPU()
|
||||
@@ -163,7 +166,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
public override void Clear()
|
||||
{
|
||||
_mainChart.Clear();
|
||||
_events.Clear();
|
||||
_events?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -173,6 +176,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
// Gather CPU events
|
||||
var events = sharedData.GetEventsCPU();
|
||||
if (_events == null)
|
||||
_events = new SamplesBuffer<ProfilingTools.ThreadStats[]>();
|
||||
_events.Add(events);
|
||||
}
|
||||
|
||||
@@ -182,11 +187,28 @@ namespace FlaxEditor.Windows.Profiler
|
||||
_showOnlyLastUpdateEvents = showOnlyLastUpdateEvents;
|
||||
_mainChart.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_events == null)
|
||||
return;
|
||||
if (_timelineLabelsCache == null)
|
||||
_timelineLabelsCache = new List<Timeline.TrackLabel>();
|
||||
if (_timelineEventsCache == null)
|
||||
_timelineEventsCache = new List<Timeline.Event>();
|
||||
|
||||
var viewRange = GetEventsViewRange();
|
||||
UpdateTimeline(ref viewRange);
|
||||
UpdateTable(ref viewRange);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineLabelsCache?.Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private struct ViewRange
|
||||
{
|
||||
public double Start;
|
||||
@@ -215,7 +237,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_showOnlyLastUpdateEvents)
|
||||
{
|
||||
// Find root event named 'Update' and use it as a view range
|
||||
if (_events.Count != 0)
|
||||
if (_events != null && _events.Count != 0)
|
||||
{
|
||||
var data = _events.Get(_mainChart.SelectedSampleIndex);
|
||||
if (data != null)
|
||||
@@ -251,14 +273,22 @@ namespace FlaxEditor.Windows.Profiler
|
||||
double scale = 100.0;
|
||||
float x = (float)((e.Start - startTime) * scale);
|
||||
float width = (float)(length * scale);
|
||||
string name = e.Name.Replace("::", ".");
|
||||
|
||||
var control = new Timeline.Event(x + xOffset, e.Depth + depthOffset, width)
|
||||
Timeline.Event control;
|
||||
if (_timelineEventsCache.Count != 0)
|
||||
{
|
||||
Name = name,
|
||||
TooltipText = string.Format("{0}, {1} ms", name, ((int)(length * 1000.0) / 1000.0f)),
|
||||
Parent = parent,
|
||||
};
|
||||
var last = _timelineEventsCache.Count - 1;
|
||||
control = _timelineEventsCache[last];
|
||||
_timelineEventsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
control = new Timeline.Event();
|
||||
}
|
||||
control.Bounds = new Rectangle(x + xOffset, (e.Depth + depthOffset) * Timeline.Event.DefaultHeight, width, Timeline.Event.DefaultHeight - 1);
|
||||
control.Name = e.Name.Replace("::", ".");
|
||||
control.TooltipText = string.Format("{0}, {1} ms", control.Name, ((int)(length * 1000.0) / 1000.0f));
|
||||
control.Parent = parent;
|
||||
|
||||
// Spawn sub events
|
||||
int childrenDepth = e.Depth + 1;
|
||||
@@ -282,10 +312,26 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
var container = _timeline.EventsContainer;
|
||||
|
||||
// Clear previous events
|
||||
container.DisposeChildren();
|
||||
|
||||
container.LockChildrenRecursive();
|
||||
container.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (container.Children.Count > idx)
|
||||
{
|
||||
var child = container.Children[idx];
|
||||
if (child is Timeline.Event e)
|
||||
{
|
||||
_timelineEventsCache.Add(e);
|
||||
child.Parent = null;
|
||||
}
|
||||
else if (child is Timeline.TrackLabel l)
|
||||
{
|
||||
_timelineLabelsCache.Add(l);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
_timeline.Height = UpdateTimelineInner(ref viewRange);
|
||||
|
||||
@@ -340,13 +386,21 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
// Add thread label
|
||||
float xOffset = 90;
|
||||
var label = new Timeline.TrackLabel
|
||||
Timeline.TrackLabel trackLabel;
|
||||
if (_timelineLabelsCache.Count != 0)
|
||||
{
|
||||
Bounds = new Rectangle(0, depthOffset * Timeline.Event.DefaultHeight, xOffset, (maxDepth + 2) * Timeline.Event.DefaultHeight),
|
||||
Name = data[i].Name,
|
||||
BackgroundColor = Style.Current.Background * 1.1f,
|
||||
Parent = container,
|
||||
};
|
||||
var last = _timelineLabelsCache.Count - 1;
|
||||
trackLabel = _timelineLabelsCache[last];
|
||||
_timelineLabelsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
trackLabel = new Timeline.TrackLabel();
|
||||
}
|
||||
trackLabel.Bounds = new Rectangle(0, depthOffset * Timeline.Event.DefaultHeight, xOffset, (maxDepth + 2) * Timeline.Event.DefaultHeight);
|
||||
trackLabel.Name = data[i].Name;
|
||||
trackLabel.BackgroundColor = Style.Current.Background * 1.1f;
|
||||
trackLabel.Parent = container;
|
||||
|
||||
// Add events
|
||||
for (int j = 0; j < events.Length; j++)
|
||||
@@ -371,7 +425,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
private void UpdateTable(ref ViewRange viewRange)
|
||||
{
|
||||
_table.DisposeChildren();
|
||||
|
||||
_table.LockChildrenRecursive();
|
||||
|
||||
UpdateTableInner(ref viewRange);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
@@ -16,7 +17,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
private readonly SingleChart _drawTimeGPU;
|
||||
private readonly Timeline _timeline;
|
||||
private readonly Table _table;
|
||||
private readonly SamplesBuffer<ProfilerGPU.Event[]> _events = new SamplesBuffer<ProfilerGPU.Event[]>();
|
||||
private SamplesBuffer<ProfilerGPU.Event[]> _events;
|
||||
private List<Timeline.Event> _timelineEventsCache;
|
||||
|
||||
public GPU()
|
||||
: base("GPU")
|
||||
@@ -118,7 +120,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
_drawTimeCPU.Clear();
|
||||
_drawTimeGPU.Clear();
|
||||
_events.Clear();
|
||||
_events?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -126,6 +128,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
// Gather GPU events
|
||||
var data = sharedData.GetEventsGPU();
|
||||
if (_events == null)
|
||||
_events = new SamplesBuffer<ProfilerGPU.Event[]>();
|
||||
_events.Add(data);
|
||||
|
||||
// Peek draw time
|
||||
@@ -138,10 +142,25 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
_drawTimeCPU.SelectedSampleIndex = selectedFrame;
|
||||
_drawTimeGPU.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_events == null)
|
||||
return;
|
||||
if (_timelineEventsCache == null)
|
||||
_timelineEventsCache = new List<Timeline.Event>();
|
||||
|
||||
UpdateTimeline();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private float AddEvent(float x, int maxDepth, int index, ProfilerGPU.Event[] events, ContainerControl parent)
|
||||
{
|
||||
ref ProfilerGPU.Event e = ref events[index];
|
||||
@@ -150,12 +169,21 @@ namespace FlaxEditor.Windows.Profiler
|
||||
float width = (float)(e.Time * scale);
|
||||
string name = new string(e.Name);
|
||||
|
||||
new Timeline.Event(x, e.Depth, width)
|
||||
Timeline.Event control;
|
||||
if (_timelineEventsCache.Count != 0)
|
||||
{
|
||||
Name = name,
|
||||
TooltipText = string.Format("{0}, {1} ms", name, ((int)(e.Time * 10000.0) / 10000.0f)),
|
||||
Parent = parent,
|
||||
};
|
||||
var last = _timelineEventsCache.Count - 1;
|
||||
control = _timelineEventsCache[last];
|
||||
_timelineEventsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
control = new Timeline.Event();
|
||||
}
|
||||
control.Bounds = new Rectangle(x, e.Depth * Timeline.Event.DefaultHeight, width, Timeline.Event.DefaultHeight - 1);
|
||||
control.Name = name;
|
||||
control.TooltipText = string.Format("{0}, {1} ms", name, ((int)(e.Time * 10000.0) / 10000.0f));
|
||||
control.Parent = parent;
|
||||
|
||||
// Spawn sub events
|
||||
int childrenDepth = e.Depth + 1;
|
||||
@@ -201,8 +229,21 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
var container = _timeline.EventsContainer;
|
||||
|
||||
// Clear previous events
|
||||
container.DisposeChildren();
|
||||
container.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (container.Children.Count > idx)
|
||||
{
|
||||
var child = container.Children[idx];
|
||||
if (child is Timeline.Event e)
|
||||
{
|
||||
_timelineEventsCache.Add(e);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
container.LockChildrenRecursive();
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
};
|
||||
|
||||
private Color _color;
|
||||
private float _nameLength;
|
||||
private string _name;
|
||||
private float _nameLength = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The default height of the event.
|
||||
@@ -50,18 +51,14 @@ namespace FlaxEditor.Windows.Profiler
|
||||
/// <summary>
|
||||
/// Gets or sets the event name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Event"/> class.
|
||||
/// </summary>
|
||||
/// <param name="x">The x position.</param>
|
||||
/// <param name="depth">The timeline row index (event depth).</param>
|
||||
/// <param name="width">The width.</param>
|
||||
public Event(float x, int depth, float width)
|
||||
: base(x, depth * DefaultHeight, width, DefaultHeight - 1)
|
||||
public string Name
|
||||
{
|
||||
_nameLength = -1;
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
_nameLength = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -88,12 +85,12 @@ namespace FlaxEditor.Windows.Profiler
|
||||
Render2D.DrawRectangle(bounds, color * 0.5f);
|
||||
|
||||
if (_nameLength < 0 && style.FontMedium)
|
||||
_nameLength = style.FontMedium.MeasureText(Name).X;
|
||||
_nameLength = style.FontMedium.MeasureText(_name).X;
|
||||
|
||||
if (_nameLength < bounds.Width + 4)
|
||||
{
|
||||
Render2D.PushClip(bounds);
|
||||
Render2D.DrawText(style.FontMedium, Name, bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
|
||||
Render2D.DrawText(style.FontMedium, _name, bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
|
||||
Render2D.PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user