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. --- src/SMAPI/Framework/Events/EventManager.cs | 5 +- src/SMAPI/Framework/Events/IManagedEvent.cs | 7 ++ src/SMAPI/Framework/Events/ManagedEvent.cs | 103 +++++++++------------------- 3 files changed, 42 insertions(+), 73 deletions(-) create mode 100644 src/SMAPI/Framework/Events/IManagedEvent.cs (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 892cbc7b..9c65a6cc 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.PerformanceCounter; namespace StardewModdingAPI.Framework.Events { @@ -173,10 +174,10 @@ namespace StardewModdingAPI.Framework.Events /// Construct an instance. /// Writes messages to the log. /// The mod registry with which to identify mods. - public EventManager(IMonitor monitor, ModRegistry modRegistry) + public EventManager(IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) { // create shortcut initializers - ManagedEvent ManageEventOf(string typeName, string eventName) => new ManagedEvent($"{typeName}.{eventName}", monitor, modRegistry); + ManagedEvent ManageEventOf(string typeName, string eventName) => new ManagedEvent($"{typeName}.{eventName}", monitor, modRegistry, performanceCounterManager); // init events (new) this.MenuChanged = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.MenuChanged)); diff --git a/src/SMAPI/Framework/Events/IManagedEvent.cs b/src/SMAPI/Framework/Events/IManagedEvent.cs new file mode 100644 index 00000000..04476866 --- /dev/null +++ b/src/SMAPI/Framework/Events/IManagedEvent.cs @@ -0,0 +1,7 @@ +namespace StardewModdingAPI.Framework.Events +{ + internal interface IManagedEvent + { + string GetName(); + } +} diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index bb915738..bba94c35 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -1,15 +1,13 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using StardewModdingAPI.Framework.Utilities; -using PerformanceCounter = StardewModdingAPI.Framework.PerformanceCounter.PerformanceCounter; +using PerformanceCounterManager = StardewModdingAPI.Framework.PerformanceCounter.PerformanceCounterManager; namespace StardewModdingAPI.Framework.Events { /// An event wrapper which intercepts and logs errors in handler code. /// The event arguments type. - internal class ManagedEvent: IPerformanceCounterEvent + internal class ManagedEvent: IManagedEvent { /********* ** Fields @@ -32,38 +30,8 @@ namespace StardewModdingAPI.Framework.Events /// The cached invocation list. private EventHandler[] CachedInvocationList; - public IDictionary PerformanceCounters { get; } = new Dictionary(); - - private readonly Stopwatch Stopwatch = new Stopwatch(); - - private long EventCallCount = 0; - - private readonly DateTime StartDateTime = DateTime.Now; - - public string GetEventName() - { - return this.EventName; - } - - public double GetGameAverageExecutionTime() - { - if (this.PerformanceCounters.TryGetValue(Constants.GamePerformanceCounterName, out PerformanceCounter.PerformanceCounter gameExecTime)) - { - return gameExecTime.GetAverage(); - } - - return 0; - } - - 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()); - } + /// The performance counter manager. + private readonly PerformanceCounterManager PerformanceCounterManager; /********* ** Public methods @@ -72,11 +40,18 @@ namespace StardewModdingAPI.Framework.Events /// A human-readable name for the event. /// Writes messages to the log. /// The mod registry with which to identify mods. - public ManagedEvent(string eventName, IMonitor monitor, ModRegistry modRegistry) + public ManagedEvent(string eventName, IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) { this.EventName = eventName; this.Monitor = monitor; this.ModRegistry = modRegistry; + this.PerformanceCounterManager = performanceCounterManager; + } + + /// Gets the event name. + public string GetName() + { + return this.EventName; } /// Get whether anything is listening to the event. @@ -99,8 +74,6 @@ namespace StardewModdingAPI.Framework.Events { this.Event += handler; this.AddTracking(mod, handler, this.Event?.GetInvocationList().Cast>()); - - } /// Remove an event handler. @@ -111,18 +84,6 @@ namespace StardewModdingAPI.Framework.Events this.RemoveTracking(handler, this.Event?.GetInvocationList().Cast>()); } - public long GetAverageCallsPerSecond() - { - long runtimeInSeconds = (long)DateTime.Now.Subtract(this.StartDateTime).TotalSeconds; - - if (runtimeInSeconds == 0) - { - return 0; - } - - return this.EventCallCount / runtimeInSeconds; - } - /// Raise the event and notify all handlers. /// The event arguments to pass. public void Raise(TEventArgs args) @@ -130,37 +91,23 @@ namespace StardewModdingAPI.Framework.Events if (this.Event == null) return; - this.EventCallCount++; + + this.PerformanceCounterManager.BeginTrackInvocation(this.EventName); foreach (EventHandler handler in this.CachedInvocationList) { try { - var performanceCounterEntry = new PerformanceCounterEntry() - { - EventTime = DateTime.Now - }; - - this.Stopwatch.Reset(); - this.Stopwatch.Start(); - handler.Invoke(null, args); - this.Stopwatch.Stop(); - performanceCounterEntry.Elapsed = this.Stopwatch.Elapsed; - - string modName = this.GetSourceMod(handler)?.DisplayName ?? Constants.GamePerformanceCounterName; - - if (!this.PerformanceCounters.ContainsKey(modName)) - { - this.PerformanceCounters.Add(modName, new PerformanceCounter.PerformanceCounter($"{modName}.{this.EventName}")); - } - this.PerformanceCounters[modName].Add(performanceCounterEntry); - + this.PerformanceCounterManager.Track(this.EventName, this.GetModNameForPerformanceCounters(handler), + () => handler.Invoke(null, args)); } catch (Exception ex) { this.LogError(handler, ex); } } + + this.PerformanceCounterManager.EndTrackInvocation(this.EventName); } /// Raise the event and notify all handlers. @@ -191,6 +138,20 @@ namespace StardewModdingAPI.Framework.Events /********* ** Private methods *********/ + + private string GetModNameForPerformanceCounters(EventHandler handler) + { + IModMetadata mod = this.GetSourceMod(handler); + + if (mod == null) + { + return Constants.GamePerformanceCounterName; + } + + return mod.HasManifest() ? mod.Manifest.UniqueID : mod.DisplayName; + + } + /// Track an event handler. /// The mod which added the handler. /// The event handler. -- cgit