max
82fe47f627
Added a simple profiler Testing LocalToWorldSystem with Parallel execution for root nodes
134 lines
3.3 KiB
C#
134 lines
3.3 KiB
C#
using System.Diagnostics;
|
|
|
|
namespace Nerfed.Runtime;
|
|
|
|
public struct ProfilerScope : IDisposable
|
|
{
|
|
public ProfilerScope(string label) {
|
|
Profiler.BeginSample(label);
|
|
}
|
|
|
|
public void Dispose() {
|
|
Profiler.EndSample();
|
|
}
|
|
}
|
|
|
|
public static class Profiler
|
|
{
|
|
public struct ProfileRecord
|
|
{
|
|
public string label;
|
|
public long startTime;
|
|
public long endTime;
|
|
public int depth;
|
|
|
|
public readonly double ElapsedMilliseconds()
|
|
{
|
|
long elapsedTicks = endTime - startTime;
|
|
return ((double)(elapsedTicks * 1000)) / Stopwatch.Frequency;
|
|
}
|
|
}
|
|
|
|
public class FrameData
|
|
{
|
|
public uint frame;
|
|
public readonly List<ProfileRecord> records = new List<ProfileRecord>();
|
|
public long startTime;
|
|
public long endTime;
|
|
|
|
public FrameData(uint frame, long startTime)
|
|
{
|
|
this.frame = frame;
|
|
this.startTime = startTime;
|
|
}
|
|
|
|
public double ElapsedMilliseconds()
|
|
{
|
|
long elapsedTicks = endTime - startTime;
|
|
return ((double)(elapsedTicks * 1000)) / Stopwatch.Frequency;
|
|
}
|
|
}
|
|
|
|
private const int maxFrames = 128;
|
|
|
|
public static readonly BoundedQueue<FrameData> frames = new(maxFrames);
|
|
public static bool recording = true;
|
|
|
|
private static readonly Stopwatch stopwatch = new Stopwatch();
|
|
private static FrameData currentFrame = null;
|
|
private static uint currentFrameIndex = 0;
|
|
private static int currentDepth = 0;
|
|
|
|
static Profiler()
|
|
{
|
|
stopwatch.Start();
|
|
}
|
|
|
|
[Conditional("PROFILING")]
|
|
public static void BeginFrame()
|
|
{
|
|
if (!recording)
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentFrame = new FrameData(currentFrameIndex, stopwatch.ElapsedTicks);
|
|
currentDepth = 0;
|
|
currentFrameIndex++;
|
|
}
|
|
|
|
[Conditional("PROFILING")]
|
|
public static void EndFrame()
|
|
{
|
|
if (!recording)
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentFrame.endTime = stopwatch.ElapsedTicks;
|
|
frames.Enqueue(currentFrame);
|
|
}
|
|
|
|
[Conditional("PROFILING")]
|
|
public static void BeginSample(string label)
|
|
{
|
|
if (!recording)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ProfileRecord record = new ProfileRecord
|
|
{
|
|
label = label,
|
|
startTime = stopwatch.ElapsedTicks,
|
|
depth = currentDepth,
|
|
};
|
|
currentFrame.records.Add(record);
|
|
//Log.Info($"{record.label} {record.depth} | {record.startTime}");
|
|
currentDepth++; // Increase depth for nested scopes
|
|
}
|
|
|
|
[Conditional("PROFILING")]
|
|
public static void EndSample()
|
|
{
|
|
if (!recording)
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentDepth--; // Decrease depth when exiting a scope
|
|
|
|
// Find the last uncompleted record at the current depth and set the end time
|
|
for (int i = currentFrame.records.Count - 1; i >= 0; i--)
|
|
{
|
|
if (currentFrame.records[i].endTime == 0)
|
|
{
|
|
ProfileRecord record = currentFrame.records[i];
|
|
record.endTime = stopwatch.ElapsedTicks;
|
|
currentFrame.records[i] = record; // Assign back to the list
|
|
//Log.Info($"{record.label} | {record.depth} | {record.endTime}");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} |