summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs')
-rw-r--r--src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs99
1 files changed, 51 insertions, 48 deletions
diff --git a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
index 3dbc693a..b2ec4c90 100644
--- a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
+++ b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
@@ -1,26 +1,32 @@
using System;
-using System.Diagnostics;
using System.Linq;
using Cyotek.Collections.Generic;
-using StardewModdingAPI.Framework.Utilities;
namespace StardewModdingAPI.Framework.PerformanceCounter
{
internal class PerformanceCounter
{
+ /// <summary>The size of the ring buffer.</summary>
private const int MAX_ENTRIES = 16384;
- public string Source { get; }
- public static Stopwatch Stopwatch = new Stopwatch();
- public static long TotalNumEventsLogged;
- public double MonitorThresholdMilliseconds { get; set; }
- public bool Monitor { get; set; }
+ /// <summary>The collection to which this performance counter belongs.</summary>
private readonly PerformanceCounterCollection ParentCollection;
+ /// <summary>The circular buffer which stores all performance counter entries</summary>
private readonly CircularBuffer<PerformanceCounterEntry> _counter;
+ /// <summary>The peak execution time</summary>
private PerformanceCounterEntry? PeakPerformanceCounterEntry;
+ /// <summary>The name of the source.</summary>
+ public string Source { get; }
+
+ /// <summary>The alert threshold in milliseconds</summary>
+ public double AlertThresholdMilliseconds { get; set; }
+
+ /// <summary>If alerting is enabled or not</summary>
+ public bool EnableAlerts { get; set; }
+
public PerformanceCounter(PerformanceCounterCollection parentCollection, string source)
{
this.ParentCollection = parentCollection;
@@ -28,90 +34,87 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
this._counter = new CircularBuffer<PerformanceCounterEntry>(PerformanceCounter.MAX_ENTRIES);
}
- public void Reset()
- {
- this._counter.Clear();
- this.PeakPerformanceCounterEntry = null;
- }
-
- public int GetAverageCallsPerSecond()
- {
- var x = this._counter.GroupBy(
- p =>
- (int) p.EventTime.Subtract(
- new DateTime(1970, 1, 1)
- ).TotalSeconds);
-
- return x.Last().Count();
- }
-
+ /// <summary>Adds a new performance counter entry to the list. Updates the peak entry and adds an alert if
+ /// monitoring is enabled and the execution time exceeds the threshold.</summary>
+ /// <param name="entry">The entry to add.</param>
public void Add(PerformanceCounterEntry entry)
{
- PerformanceCounter.Stopwatch.Start();
this._counter.Put(entry);
- if (this.Monitor && entry.Elapsed.TotalMilliseconds > this.MonitorThresholdMilliseconds)
- {
- this.ParentCollection.AddAlert(entry.Elapsed.TotalMilliseconds, this.MonitorThresholdMilliseconds, new AlertContext(this.Source, entry.Elapsed.TotalMilliseconds));
- }
+ if (this.EnableAlerts && entry.ElapsedMilliseconds > this.AlertThresholdMilliseconds)
+ this.ParentCollection.AddAlert(entry.ElapsedMilliseconds, this.AlertThresholdMilliseconds,
+ new AlertContext(this.Source, entry.ElapsedMilliseconds));
if (this.PeakPerformanceCounterEntry == null)
- {
this.PeakPerformanceCounterEntry = entry;
- }
else
{
- if (entry.Elapsed.TotalMilliseconds > this.PeakPerformanceCounterEntry.Value.Elapsed.TotalMilliseconds)
- {
+ if (entry.ElapsedMilliseconds > this.PeakPerformanceCounterEntry.Value.ElapsedMilliseconds)
this.PeakPerformanceCounterEntry = entry;
- }
}
+ }
- PerformanceCounter.Stopwatch.Stop();
- PerformanceCounter.TotalNumEventsLogged++;
+ /// <summary>Clears all performance counter entries and resets the peak entry.</summary>
+ public void Reset()
+ {
+ this._counter.Clear();
+ this.PeakPerformanceCounterEntry = null;
}
+ /// <summary>Returns the peak entry.</summary>
+ /// <returns>The peak entry.</returns>
public PerformanceCounterEntry? GetPeak()
{
return this.PeakPerformanceCounterEntry;
}
+ /// <summary>Resets the peak entry.</summary>
public void ResetPeak()
{
this.PeakPerformanceCounterEntry = null;
}
+ /// <summary>Returns the last entry added to the list.</summary>
+ /// <returns>The last entry</returns>
public PerformanceCounterEntry? GetLastEntry()
{
if (this._counter.IsEmpty)
- {
return null;
- }
+
return this._counter.PeekLast();
}
+ /// <summary>Returns the average execution time of all entries.</summary>
+ /// <returns>The average execution time in milliseconds.</returns>
public double GetAverage()
{
if (this._counter.IsEmpty)
- {
return 0;
- }
- return this._counter.Average(p => p.Elapsed.TotalMilliseconds);
+ return this._counter.Average(p => p.ElapsedMilliseconds);
}
- public double GetAverage(TimeSpan range)
+ /// <summary>Returns the average over a given time span.</summary>
+ /// <param name="range">The time range to retrieve.</param>
+ /// <param name="relativeTo">The DateTime from which to start the average. Defaults to DateTime.UtcNow if null</param>
+ /// <returns>The average execution time in milliseconds.</returns>
+ /// <remarks>
+ /// The relativeTo parameter specifies from which point in time the range is subtracted. Example:
+ /// If DateTime is set to 60 seconds ago, and the range is set to 60 seconds, the method would return
+ /// the average between all entries between 120s ago and 60s ago.
+ /// </remarks>
+ public double GetAverage(TimeSpan range, DateTime? relativeTo = null)
{
if (this._counter.IsEmpty)
- {
return 0;
- }
- var lastTime = this._counter.Max(x => x.EventTime);
- var start = lastTime.Subtract(range);
+ if (relativeTo == null)
+ relativeTo = DateTime.UtcNow;
+
+ DateTime start = relativeTo.Value.Subtract(range);
- var entries = this._counter.Where(x => (x.EventTime >= start) && (x.EventTime <= lastTime));
- return entries.Average(x => x.Elapsed.TotalMilliseconds);
+ var entries = this._counter.Where(x => (x.EventTime >= start) && (x.EventTime <= relativeTo));
+ return entries.Average(x => x.ElapsedMilliseconds);
}
}
}