summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
authorDrachenkaetzchen <felicia@drachenkatze.org>2020-01-15 19:08:50 +0100
committerDrachenkaetzchen <felicia@drachenkatze.org>2020-01-15 19:08:50 +0100
commit84973ce5727ad20fe8b8ba4f89e59c8b754f799e (patch)
tree90c7f55d3a42ec73afdf86cebd8ae980ec3c1c4d /src/SMAPI/Framework
parent238b5db4f7f2f05e8967cc5eda761733d4bf35b4 (diff)
downloadSMAPI-84973ce5727ad20fe8b8ba4f89e59c8b754f799e.tar.gz
SMAPI-84973ce5727ad20fe8b8ba4f89e59c8b754f799e.tar.bz2
SMAPI-84973ce5727ad20fe8b8ba4f89e59c8b754f799e.zip
Added peak execution time over the last 60 seconds
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/PerformanceCounter/PeakEntry.cs24
-rw-r--r--src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs20
-rw-r--r--src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs47
-rw-r--r--src/SMAPI/Framework/PerformanceCounter/PerformanceCounterManager.cs5
4 files changed, 88 insertions, 8 deletions
diff --git a/src/SMAPI/Framework/PerformanceCounter/PeakEntry.cs b/src/SMAPI/Framework/PerformanceCounter/PeakEntry.cs
new file mode 100644
index 00000000..95dc11f4
--- /dev/null
+++ b/src/SMAPI/Framework/PerformanceCounter/PeakEntry.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+
+namespace StardewModdingAPI.Framework.PerformanceCounter
+{
+ internal struct PeakEntry
+ {
+ /// <summary>The actual execution time in milliseconds.</summary>
+ public readonly double ExecutionTimeMilliseconds;
+
+ /// <summary>The DateTime when the entry occured.</summary>
+ public DateTime EventTime;
+
+ /// <summary>The context list, which records all sources involved in exceeding the threshold.</summary>
+ public readonly List<AlertContext> Context;
+
+ public PeakEntry(double executionTimeMilliseconds, DateTime eventTime, List<AlertContext> context)
+ {
+ this.ExecutionTimeMilliseconds = executionTimeMilliseconds;
+ this.EventTime = eventTime;
+ this.Context = context;
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
index 33ddde2f..3d902e16 100644
--- a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
+++ b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounter.cs
@@ -68,6 +68,26 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
return this.PeakPerformanceCounterEntry;
}
+ /// <summary>Returns the peak entry.</summary>
+ /// <returns>The peak entry.</returns>
+ public PerformanceCounterEntry? GetPeak(TimeSpan range, DateTime? relativeTo = null)
+ {
+ if (this._counter.IsEmpty)
+ return null;
+
+ if (relativeTo == null)
+ relativeTo = DateTime.UtcNow;
+
+ DateTime start = relativeTo.Value.Subtract(range);
+
+ var entries = this._counter.Where(x => (x.EventTime >= start) && (x.EventTime <= relativeTo)).ToList();
+
+ if (!entries.Any())
+ return null;
+
+ return entries.OrderByDescending(x => x.ElapsedMilliseconds).First();
+ }
+
/// <summary>Resets the peak entry.</summary>
public void ResetPeak()
{
diff --git a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs
index b48efd67..fe14ebf8 100644
--- a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs
+++ b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs
@@ -2,11 +2,15 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using Cyotek.Collections.Generic;
namespace StardewModdingAPI.Framework.PerformanceCounter
{
internal class PerformanceCounterCollection
{
+ /// <summary>The size of the ring buffer.</summary>
+ private const int MAX_ENTRIES = 16384;
+
/// <summary>The list of triggered performance counters.</summary>
private readonly List<AlertContext> TriggeredPerformanceCounters = new List<AlertContext>();
@@ -22,6 +26,10 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
/// <summary>The number of invocations of this collection.</summary>
private long CallCount;
+ /// <summary>The circular buffer which stores all peak invocations</summary>
+ private readonly CircularBuffer<PeakEntry> PeakInvocations;
+
+ /// <summary>The associated performance counters.</summary>
public IDictionary<string, PerformanceCounter> PerformanceCounters { get; } = new Dictionary<string, PerformanceCounter>();
/// <summary>The name of this collection.</summary>
@@ -39,6 +47,7 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
public PerformanceCounterCollection(PerformanceCounterManager performanceCounterManager, string name, bool isImportant)
{
+ this.PeakInvocations = new CircularBuffer<PeakEntry>(PerformanceCounterCollection.MAX_ENTRIES);
this.Name = name;
this.PerformanceCounterManager = performanceCounterManager;
this.IsImportant = isImportant;
@@ -46,6 +55,7 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
public PerformanceCounterCollection(PerformanceCounterManager performanceCounterManager, string name)
{
+ this.PeakInvocations = new CircularBuffer<PeakEntry>(PerformanceCounterCollection.MAX_ENTRIES);
this.PerformanceCounterManager = performanceCounterManager;
this.Name = name;
}
@@ -89,15 +99,30 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
return 0;
}
+ public double GetPeakExecutionTime(TimeSpan range, DateTime? relativeTo = null)
+ {
+ if (this.PeakInvocations.IsEmpty)
+ return 0;
+
+ if (relativeTo == null)
+ relativeTo = DateTime.UtcNow;
+
+ DateTime start = relativeTo.Value.Subtract(range);
+
+ var entries = this.PeakInvocations.Where(x => (x.EventTime >= start) && (x.EventTime <= relativeTo)).ToList();
+
+ if (!entries.Any())
+ return 0;
+
+ return entries.OrderByDescending(x => x.ExecutionTimeMilliseconds).First().ExecutionTimeMilliseconds;
+ }
+
/// <summary>Begins tracking the invocation of this collection.</summary>
public void BeginTrackInvocation()
{
- if (this.EnableAlerts)
- {
- this.TriggeredPerformanceCounters.Clear();
- this.InvocationStopwatch.Reset();
- this.InvocationStopwatch.Start();
- }
+ this.TriggeredPerformanceCounters.Clear();
+ this.InvocationStopwatch.Reset();
+ this.InvocationStopwatch.Start();
this.CallCount++;
}
@@ -106,10 +131,15 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
/// and the invocation time exceeds the threshold.</summary>
public void EndTrackInvocation()
{
- if (!this.EnableAlerts) return;
-
this.InvocationStopwatch.Stop();
+ this.PeakInvocations.Put(
+ new PeakEntry(this.InvocationStopwatch.Elapsed.TotalMilliseconds,
+ DateTime.UtcNow,
+ this.TriggeredPerformanceCounters));
+
+ if (!this.EnableAlerts) return;
+
if (this.InvocationStopwatch.Elapsed.TotalMilliseconds >= this.AlertThresholdMilliseconds)
this.AddAlert(this.InvocationStopwatch.Elapsed.TotalMilliseconds,
this.AlertThresholdMilliseconds, this.TriggeredPerformanceCounters);
@@ -144,6 +174,7 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
/// <summary>Resets all performance counters in this collection.</summary>
public void Reset()
{
+ this.PeakInvocations.Clear();
foreach (var i in this.PerformanceCounters)
i.Value.Reset();
}
diff --git a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterManager.cs b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterManager.cs
index 49720431..a8e20eda 100644
--- a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterManager.cs
+++ b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterManager.cs
@@ -33,6 +33,11 @@ namespace StardewModdingAPI.Framework.PerformanceCounter
/// <summary>Resets all performance counters in all collections.</summary>
public void Reset()
{
+ foreach (PerformanceCounterCollection collection in this.PerformanceCounterCollections)
+ {
+ collection.Reset();
+ }
+
foreach (var eventPerformanceCounter in
this.PerformanceCounterCollections.SelectMany(performanceCounter => performanceCounter.PerformanceCounters))
{