using Qrakhen.Qamp.Core.Logging; using System.Diagnostics; using System.Runtime.CompilerServices; namespace Qrakhen.Qamp.Core; public static class Benchmark { private static readonly Dictionary _clocks = new(); public static bool Active { get; set; } private static readonly ILogger _logger = LoggerService.Get(nameof(Benchmark)); private static string MakeKey(string? id, string? member, string? file) { if (member == null) return "global"; return $"{file?.Split('\\').Last() ?? "unknown"}{(id == null ? "" : $"<{id}>")}::{member}"; } public static void Start( string? message = null, string? id = null, [CallerMemberName] string? member = null, [CallerFilePath] string? file = null, [CallerLineNumber] int? line = null) { if (!Active) return; string key = MakeKey(id, member, file); if (!_clocks.TryGetValue(key, out Stopwatch? sw)) { sw = _clocks[key] = new Stopwatch(); IO.Console.Write($" ::: Registered new benchmark clock '{key}'\n"); } if (!string.IsNullOrEmpty(message)) IO.Console.Write($" ::: {key}:{line} > {message}\n"); if (sw.IsRunning) IO.Console.Write($" ::: {key}:{line} > already running with an elapsed time of {sw.Elapsed}. clock was reset.\n"); sw.Reset(); sw.Start(); } public static long Report( string? message = null, string? id = null, bool keep = true, [CallerMemberName] string? member = null, [CallerFilePath] string? file = null, [CallerLineNumber] int? line = null) { if (!Active) return 0; string key = MakeKey(id, member, file); if (!_clocks.TryGetValue(key, out Stopwatch sw)) { _logger.Debug($"No clock found for '{key}', start one first using Benchmark.Start()"); return 0; } sw.Stop(); IO.Console.Write($" ::: {key}:{line} > {message ?? "Elapsed"}: {sw.Elapsed}"); if (keep) sw.Start(); return sw.ElapsedMilliseconds; } public static long End( string? message = null, string? id = null, [CallerMemberName] string? member = null, [CallerFilePath] string? file = null, [CallerLineNumber] int? line = null) { if (!Active) return 0; return Report(message, id, false, member, file, line); } }