Add profiler warmup overhead tracking and tooltip display
This commit is contained in:
@@ -194,7 +194,16 @@ namespace Nerfed.Editor.Systems
|
|||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text($"{node.SelfMilliseconds():0.000}");
|
ImGui.Text($"{node.SelfMilliseconds():0.000}");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
if (node.ProfilerSetupBytes > 0)
|
||||||
|
{
|
||||||
|
ImGui.Text($"{node.AllocatedBytes} !");
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"{node.ProfilerSetupBytes} B is profiler warmup overhead");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ImGui.Text($"{node.AllocatedBytes}");
|
ImGui.Text($"{node.AllocatedBytes}");
|
||||||
|
}
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text($"{node.SelfAllocatedBytes()}");
|
ImGui.Text($"{node.SelfAllocatedBytes()}");
|
||||||
|
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ public static class Profiler
|
|||||||
public int ManagedThreadId { get; private set; }
|
public int ManagedThreadId { get; private set; }
|
||||||
public List<ScopeNode> Children { get; } = new List<ScopeNode>();
|
public List<ScopeNode> Children { get; } = new List<ScopeNode>();
|
||||||
public long AllocatedBytes { get; private set; }
|
public long AllocatedBytes { get; private set; }
|
||||||
|
public long ProfilerSetupBytes { get; private set; }
|
||||||
internal ScopeNode Parent { get; private set; }
|
internal ScopeNode Parent { get; private set; }
|
||||||
internal long ChildrenDurationTicks { get; private set; }
|
internal long ChildrenDurationTicks { get; private set; }
|
||||||
internal long ChildrenAllocatedBytes { get; private set; }
|
internal long ChildrenAllocatedBytes { get; private set; }
|
||||||
@@ -451,6 +452,7 @@ public static class Profiler
|
|||||||
ChildrenDurationTicks = 0;
|
ChildrenDurationTicks = 0;
|
||||||
ChildrenAllocatedBytes = 0;
|
ChildrenAllocatedBytes = 0;
|
||||||
AllocatedBytes = 0;
|
AllocatedBytes = 0;
|
||||||
|
ProfilerSetupBytes = 0;
|
||||||
Children.Clear();
|
Children.Clear();
|
||||||
allocatedBytesAtStart = GC.GetAllocatedBytesForCurrentThread();
|
allocatedBytesAtStart = GC.GetAllocatedBytesForCurrentThread();
|
||||||
}
|
}
|
||||||
@@ -463,9 +465,11 @@ public static class Profiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
EndTime = Stopwatch.GetTimestamp();
|
EndTime = Stopwatch.GetTimestamp();
|
||||||
AllocatedBytes = Math.Max(0, GC.GetAllocatedBytesForCurrentThread() - allocatedBytesAtStart);
|
|
||||||
if (Parent != null)
|
if (Parent != null)
|
||||||
{
|
{
|
||||||
|
// Root nodes are ended from FinalizeCurrentFrame on the main thread, so their
|
||||||
|
// GC counter would be from the wrong thread. Only track alloc on non-root nodes.
|
||||||
|
AllocatedBytes = Math.Max(0, GC.GetAllocatedBytesForCurrentThread() - allocatedBytesAtStart);
|
||||||
Parent.ChildrenDurationTicks += Math.Max(0, EndTime - StartTime);
|
Parent.ChildrenDurationTicks += Math.Max(0, EndTime - StartTime);
|
||||||
Parent.ChildrenAllocatedBytes += AllocatedBytes;
|
Parent.ChildrenAllocatedBytes += AllocatedBytes;
|
||||||
}
|
}
|
||||||
@@ -488,6 +492,12 @@ public static class Profiler
|
|||||||
return Math.Max(0, AllocatedBytes - ChildrenAllocatedBytes);
|
return Math.Max(0, AllocatedBytes - ChildrenAllocatedBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called after all profiler setup (Children.Add + scopes.Push) to measure overhead within this scope's window.
|
||||||
|
internal void NoteSetupOverhead()
|
||||||
|
{
|
||||||
|
ProfilerSetupBytes = Math.Max(0, GC.GetAllocatedBytesForCurrentThread() - allocatedBytesAtStart);
|
||||||
|
}
|
||||||
|
|
||||||
internal ScopeNode AddChild(string label, string category, ulong tagMask)
|
internal ScopeNode AddChild(string label, string category, ulong tagMask)
|
||||||
{
|
{
|
||||||
ScopeNode child = RentNode(label, category, tagMask, ManagedThreadId, this);
|
ScopeNode child = RentNode(label, category, tagMask, ManagedThreadId, this);
|
||||||
@@ -648,6 +658,7 @@ public static class Profiler
|
|||||||
|
|
||||||
ScopeNode newScope = scopes.Peek().AddChild(label, category, tagMask);
|
ScopeNode newScope = scopes.Peek().AddChild(label, category, tagMask);
|
||||||
scopes.Push(newScope);
|
scopes.Push(newScope);
|
||||||
|
newScope.NoteSetupOverhead();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Conditional("PROFILING")]
|
[Conditional("PROFILING")]
|
||||||
|
|||||||
@@ -372,6 +372,11 @@ public static class ProfilerVisualizer
|
|||||||
ImGui.Text($"Timeline Start: {hover.StartInTimelineMs:0.000} ms");
|
ImGui.Text($"Timeline Start: {hover.StartInTimelineMs:0.000} ms");
|
||||||
ImGui.Text($"Timeline End: {hover.EndInTimelineMs:0.000} ms");
|
ImGui.Text($"Timeline End: {hover.EndInTimelineMs:0.000} ms");
|
||||||
ImGui.Text($"Children: {hover.Node.Children.Count}");
|
ImGui.Text($"Children: {hover.Node.Children.Count}");
|
||||||
|
if (hover.Node.ProfilerSetupBytes > 0)
|
||||||
|
{
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.TextColored(new Vector4(1f, 0.75f, 0f, 1f), $"\u26a0 {hover.Node.ProfilerSetupBytes} B of alloc is profiler warmup overhead");
|
||||||
|
}
|
||||||
ImGui.EndTooltip();
|
ImGui.EndTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user