Nerfed/Nerfed.Runtime/Profiler.cs
max 82fe47f627 Profiler and LocalToWorldThreadedSystem
Added a simple profiler
Testing LocalToWorldSystem with Parallel execution for root nodes
2024-10-19 23:41:05 +02:00

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;
}
}
}
}