/ src / ARMeilleure / Statistics.cs
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  }