Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.2 KiB

1 year ago
using System.Diagnostics;
using System.Reactive.Disposables;
1 year ago
using System.Runtime.CompilerServices;
using System.Text;
namespace StabilityMatrix.Core.Helper;
public class CodeTimer : IDisposable
{
private static readonly Stack<CodeTimer> RunningTimers = new();
1 year ago
private readonly string name;
private readonly Stopwatch stopwatch;
private CodeTimer? ParentTimer { get; }
private List<CodeTimer> SubTimers { get; } = new();
public CodeTimer(string postFix = "", [CallerMemberName] string callerName = "")
1 year ago
{
name = $"{callerName}" + (string.IsNullOrEmpty(postFix) ? "" : $" ({postFix})");
1 year ago
stopwatch = Stopwatch.StartNew();
1 year ago
// Set parent as the top of the stack
if (RunningTimers.TryPeek(out var timer))
{
ParentTimer = timer;
timer.SubTimers.Add(this);
}
1 year ago
// Add ourselves to the stack
RunningTimers.Push(this);
}
/// <summary>
/// Starts a new timer and returns it if DEBUG is defined, otherwise returns an empty IDisposable
/// </summary>
/// <param name="postFix"></param>
/// <param name="callerName"></param>
/// <returns></returns>
public static IDisposable StartDebug(
string postFix = "",
[CallerMemberName] string callerName = ""
)
{
#if DEBUG
return new CodeTimer(postFix, callerName);
#else
return Disposable.Empty;
#endif
}
1 year ago
/// <summary>
/// Formats a TimeSpan into a string. Chooses the most appropriate unit of time.
/// </summary>
private static string FormatTime(TimeSpan duration)
{
if (duration.TotalSeconds < 1)
{
return $"{duration.TotalMilliseconds:0.00}ms";
}
if (duration.TotalMinutes < 1)
{
return $"{duration.TotalSeconds:0.00}s";
}
if (duration.TotalHours < 1)
{
return $"{duration.TotalMinutes:0.00}m";
}
return $"{duration.TotalHours:0.00}h";
}
private static void OutputDebug(string message)
{
Debug.WriteLine(message);
}
/// <summary>
/// Get results for this timer and all sub timers recursively
/// </summary>
private string GetResult()
{
var builder = new StringBuilder();
1 year ago
builder.AppendLine($"{name}: took {FormatTime(stopwatch.Elapsed)}");
1 year ago
foreach (var timer in SubTimers)
{
// For each sub timer layer, add a `|-` prefix
builder.AppendLine($"|- {timer.GetResult()}");
}
1 year ago
return builder.ToString();
}
1 year ago
public void Dispose()
{
stopwatch.Stop();
1 year ago
// Remove ourselves from the stack
if (RunningTimers.TryPop(out var timer))
{
if (timer != this)
{
throw new InvalidOperationException("Timer stack is corrupted");
}
}
else
{
throw new InvalidOperationException("Timer stack is empty");
}
1 year ago
// If we're a root timer, output all results
if (ParentTimer is null)
{
OutputDebug(GetResult());
SubTimers.Clear();
}
1 year ago
GC.SuppressFinalize(this);
}
}