Statistics.cs
1 #if M_PROFILE 2 using System; 3 #endif 4 using System.Collections.Concurrent; 5 using System.Collections.Generic; 6 using System.Diagnostics; 7 using System.Linq; 8 using System.Text; 9 10 namespace ARMeilleure 11 { 12 public static class Statistics 13 { 14 private const int ReportMaxFunctions = 100; 15 16 #if M_PROFILE 17 [ThreadStatic] 18 private static Stopwatch _executionTimer; 19 #endif 20 21 private static readonly ConcurrentDictionary<ulong, long> _ticksPerFunction; 22 23 static Statistics() 24 { 25 _ticksPerFunction = new ConcurrentDictionary<ulong, long>(); 26 } 27 28 public static void InitializeTimer() 29 { 30 #if M_PROFILE 31 if (_executionTimer == null) 32 { 33 _executionTimer = new Stopwatch(); 34 } 35 #endif 36 } 37 38 internal static void StartTimer() 39 { 40 #if M_PROFILE 41 _executionTimer.Restart(); 42 #endif 43 } 44 45 internal static void StopTimer(ulong funcAddr) 46 { 47 #if M_PROFILE 48 _executionTimer.Stop(); 49 50 long ticks = _executionTimer.ElapsedTicks; 51 52 TicksPerFunction.AddOrUpdate(funcAddr, ticks, (key, oldTicks) => oldTicks + ticks); 53 #endif 54 } 55 56 internal static void ResumeTimer() 57 { 58 #if M_PROFILE 59 _executionTimer.Start(); 60 #endif 61 } 62 63 internal static void PauseTimer() 64 { 65 #if M_PROFILE 66 _executionTimer.Stop(); 67 #endif 68 } 69 70 public static string GetReport() 71 { 72 int count = 0; 73 74 StringBuilder sb = new(); 75 76 sb.AppendLine(" Function address | Time"); 77 sb.AppendLine("--------------------------"); 78 79 KeyValuePair<ulong, long>[] funcTable = _ticksPerFunction.ToArray(); 80 81 foreach (KeyValuePair<ulong, long> kv in funcTable.OrderByDescending(x => x.Value)) 82 { 83 long timeInMs = (kv.Value * 1000) / Stopwatch.Frequency; 84 85 sb.AppendLine($" 0x{kv.Key:X16} | {timeInMs} ms"); 86 87 if (count++ >= ReportMaxFunctions) 88 { 89 break; 90 } 91 } 92 93 return sb.ToString(); 94 } 95 } 96 }