From 280dc911839f8996cddd9804f3f545cc38d20243 Mon Sep 17 00:00:00 2001 From: Drachenkaetzchen Date: Sat, 11 Jan 2020 15:45:45 +0100 Subject: Reworked the console implementation, added monitoring. Some internal refactoring. --- .../PerformanceCounterCollection.cs | 144 +++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs (limited to 'src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs') diff --git a/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs new file mode 100644 index 00000000..343fddf6 --- /dev/null +++ b/src/SMAPI/Framework/PerformanceCounter/PerformanceCounterCollection.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using StardewModdingAPI.Framework.Utilities; + +namespace StardewModdingAPI.Framework.PerformanceCounter +{ + internal class PerformanceCounterCollection + { + public IDictionary PerformanceCounters { get; } = new Dictionary(); + private DateTime StartDateTime = DateTime.Now; + private long CallCount; + public string Name { get; private set; } + public bool IsImportant { get; set; } + private readonly Stopwatch Stopwatch = new Stopwatch(); + private readonly PerformanceCounterManager PerformanceCounterManager; + public double MonitorThresholdMilliseconds { get; set; } + public bool Monitor { get; set; } + private readonly List TriggeredPerformanceCounters = new List(); + + public PerformanceCounterCollection(PerformanceCounterManager performanceCounterManager, string name, bool isImportant) + { + this.Name = name; + this.PerformanceCounterManager = performanceCounterManager; + this.IsImportant = isImportant; + } + + public PerformanceCounterCollection(PerformanceCounterManager performanceCounterManager, string name) + { + this.PerformanceCounterManager = performanceCounterManager; + this.Name = name; + } + + public void Track(string source, PerformanceCounterEntry entry) + { + if (!this.PerformanceCounters.ContainsKey(source)) + { + this.PerformanceCounters.Add(source, new PerformanceCounter(this, source)); + } + this.PerformanceCounters[source].Add(entry); + + if (this.Monitor) + { + this.TriggeredPerformanceCounters.Add(new AlertContext(source, entry.Elapsed.TotalMilliseconds)); + } + } + + public double GetModsAverageExecutionTime() + { + return this.PerformanceCounters.Where(p => p.Key != Constants.GamePerformanceCounterName).Sum(p => p.Value.GetAverage()); + } + + public double GetAverageExecutionTime() + { + return this.PerformanceCounters.Sum(p => p.Value.GetAverage()); + } + + public double GetGameAverageExecutionTime() + { + if (this.PerformanceCounters.TryGetValue(Constants.GamePerformanceCounterName, out PerformanceCounter gameExecTime)) + { + return gameExecTime.GetAverage(); + } + + return 0; + } + + public void BeginTrackInvocation() + { + if (this.Monitor) + { + this.TriggeredPerformanceCounters.Clear(); + this.Stopwatch.Reset(); + this.Stopwatch.Start(); + } + + this.CallCount++; + + } + + public void EndTrackInvocation() + { + if (!this.Monitor) return; + + this.Stopwatch.Stop(); + if (this.Stopwatch.Elapsed.TotalMilliseconds >= this.MonitorThresholdMilliseconds) + { + this.AddAlert(this.Stopwatch.Elapsed.TotalMilliseconds, + this.MonitorThresholdMilliseconds, this.TriggeredPerformanceCounters); + } + } + + public void AddAlert(double executionTimeMilliseconds, double threshold, List alerts) + { + this.PerformanceCounterManager.AddAlert(new AlertEntry(this, executionTimeMilliseconds, + threshold, alerts)); + } + + public void AddAlert(double executionTimeMilliseconds, double threshold, AlertContext alert) + { + this.AddAlert(executionTimeMilliseconds, threshold, new List() {alert}); + } + + public void ResetCallsPerSecond() + { + this.CallCount = 0; + this.StartDateTime = DateTime.Now; + } + + public void Reset() + { + foreach (var i in this.PerformanceCounters) + { + i.Value.Reset(); + i.Value.ResetPeak(); + } + } + + public void ResetSource(string source) + { + foreach (var i in this.PerformanceCounters) + { + if (i.Value.Source.Equals(source, StringComparison.InvariantCultureIgnoreCase)) + { + i.Value.Reset(); + i.Value.ResetPeak(); + } + } + } + + public long GetAverageCallsPerSecond() + { + long runtimeInSeconds = (long) DateTime.Now.Subtract(this.StartDateTime).TotalSeconds; + + if (runtimeInSeconds == 0) + { + return 0; + } + + return this.CallCount / runtimeInSeconds; + } + } +} -- cgit