Client LuaCsForBarotrauma
PerformanceCounter.cs
1 using Microsoft.Xna.Framework;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq;
5 
6 namespace Barotrauma
7 {
8  public class PerformanceCounter
9  {
10  private readonly object mutex = new object();
11 
12  public double AverageFramesPerSecond { get; private set; }
13  public double CurrentFramesPerSecond { get; private set; }
14 
15  public double AverageFramesPerSecondInPastMinute { get; private set; }
16 
17  public const int MaximumSamples = 10;
18 
19  private readonly Queue<double> sampleBuffer = new Queue<double>();
20 
21  private readonly Queue<double> averageFramesPerSecondBuffer = new Queue<double>();
22 
23  private readonly Stopwatch timer = new Stopwatch();
24  private long lastSecondMark = 0;
25  private long lastMinuteMark = 0;
26 
27  public class TickInfo
28  {
29  public Queue<long> ElapsedTicks { get; set; } = new Queue<long>();
30  public long AvgTicksPerFrame { get; set; }
31  }
32 
33  private readonly Dictionary<string, Queue<long>> elapsedTicks = new Dictionary<string, Queue<long>>();
34  private readonly Dictionary<string, long> avgTicksPerFrame = new Dictionary<string, long>();
35 
36 #if CLIENT
37  internal Graph UpdateTimeGraph = new Graph(500), DrawTimeGraph = new Graph(500);
38 #endif
39 
40  private readonly List<string> tempSavedIdentifiers = new List<string>();
41 
42  public IReadOnlyList<string> GetSavedIdentifiers
43  {
44  get
45  {
46  lock (mutex)
47  {
48  tempSavedIdentifiers.Clear();
49  tempSavedIdentifiers.AddRange(avgTicksPerFrame.Keys);
50  }
51  return tempSavedIdentifiers;
52  }
53  }
54 
56  {
57  timer.Start();
58  }
59 
60  public void AddElapsedTicks(string identifier, long ticks)
61  {
62  lock (mutex)
63  {
64  if (!elapsedTicks.ContainsKey(identifier)) { elapsedTicks.Add(identifier, new Queue<long>()); }
65  elapsedTicks[identifier].Enqueue(ticks);
66 
67  if (elapsedTicks[identifier].Count > MaximumSamples)
68  {
69  elapsedTicks[identifier].Dequeue();
70  avgTicksPerFrame[identifier] = (long)elapsedTicks[identifier].Average(i => i);
71  }
72  }
73  }
74 
75  public float GetAverageElapsedMillisecs(string identifier)
76  {
77  long ticksPerFrame = 0;
78  lock (mutex)
79  {
80  avgTicksPerFrame.TryGetValue(identifier, out ticksPerFrame);
81  }
82  return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
83  }
84 
85  public bool Update(double deltaTime)
86  {
87  if (deltaTime == 0.0f) { return false; }
88 
89  CurrentFramesPerSecond = 1.0 / deltaTime;
90 
91  sampleBuffer.Enqueue(CurrentFramesPerSecond);
92  if (sampleBuffer.Count > MaximumSamples)
93  {
94  sampleBuffer.Dequeue();
95  AverageFramesPerSecond = sampleBuffer.Average();
96  }
97  else
98  {
100  }
101 
102  long currentTime = timer.ElapsedMilliseconds;
103  long currentSecond = currentTime / 1000;
104 
105 
106  if (currentSecond > lastSecondMark)
107  {
108  averageFramesPerSecondBuffer.Enqueue(AverageFramesPerSecond);
109  lastSecondMark = currentSecond;
110  }
111 
112  if (currentTime - lastMinuteMark >= 60 * 1000)
113  {
114  //the FPS could be even higher than this on a high-end monitor, but let's restrict it to 144 to reduce the number of distinct event IDs
115  const int MaxFPS = 144;
116  AverageFramesPerSecondInPastMinute = averageFramesPerSecondBuffer.Average();
117  GameAnalyticsManager.AddDesignEvent($"FPS:{MathHelper.Clamp((int)AverageFramesPerSecondInPastMinute, 0, MaxFPS)}");
118  GameAnalyticsManager.AddDesignEvent($"FPSLowest:{MathHelper.Clamp((int)averageFramesPerSecondBuffer.Min(), 0, MaxFPS)}");
119  averageFramesPerSecondBuffer.Clear();
120  lastMinuteMark = currentTime;
121  }
122 
123  return true;
124  }
125  }
126 }
float GetAverageElapsedMillisecs(string identifier)
IReadOnlyList< string > GetSavedIdentifiers
void AddElapsedTicks(string identifier, long ticks)
bool Update(double deltaTime)