From a751252c4ee3b48977d5d24c36a4e4e5466f93db Mon Sep 17 00:00:00 2001 From: Drachenkaetzchen Date: Fri, 10 Jan 2020 01:27:56 +0100 Subject: Initial commit of the performance counters --- src/SMAPI/Framework/Events/ManagedEvent.cs | 71 +++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index 2afe7a03..9a5cb174 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using StardewModdingAPI.Framework.Utilities; +using PerformanceCounter = StardewModdingAPI.Framework.Utilities.PerformanceCounter; namespace StardewModdingAPI.Framework.Events { /// An event wrapper which intercepts and logs errors in handler code. /// The event arguments type. - internal class ManagedEvent + internal class ManagedEvent: IPerformanceCounterEvent { /********* ** Fields @@ -29,6 +32,38 @@ 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 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()); + } /********* ** Public methods @@ -64,6 +99,8 @@ namespace StardewModdingAPI.Framework.Events { this.Event += handler; this.AddTracking(mod, handler, this.Event?.GetInvocationList().Cast>()); + + } /// Remove an event handler. @@ -74,6 +111,18 @@ 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) @@ -81,11 +130,31 @@ namespace StardewModdingAPI.Framework.Events if (this.Event == null) return; + this.EventCallCount++; + 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($"{modName}.{this.EventName}")); + } + this.PerformanceCounters[modName].Add(performanceCounterEntry); + } catch (Exception ex) { -- cgit From 47f626cc99c93a28b2d6867ed6cc717b39ec062c Mon Sep 17 00:00:00 2001 From: Drachenkaetzchen Date: Fri, 10 Jan 2020 14:08:25 +0100 Subject: Moved most PerformanceCounter logic out of SCore into the new PerformanceCounterManager, some namespace refactoring --- src/SMAPI/Framework/Events/ManagedEvent.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index 9a5cb174..bb915738 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using StardewModdingAPI.Framework.Utilities; -using PerformanceCounter = StardewModdingAPI.Framework.Utilities.PerformanceCounter; +using PerformanceCounter = StardewModdingAPI.Framework.PerformanceCounter.PerformanceCounter; namespace StardewModdingAPI.Framework.Events { @@ -32,7 +32,7 @@ namespace StardewModdingAPI.Framework.Events /// The cached invocation list. private EventHandler[] CachedInvocationList; - public IDictionary PerformanceCounters { get; } = new Dictionary(); + public IDictionary PerformanceCounters { get; } = new Dictionary(); private readonly Stopwatch Stopwatch = new Stopwatch(); @@ -47,7 +47,7 @@ namespace StardewModdingAPI.Framework.Events public double GetGameAverageExecutionTime() { - if (this.PerformanceCounters.TryGetValue(Constants.GamePerformanceCounterName, out PerformanceCounter gameExecTime)) + if (this.PerformanceCounters.TryGetValue(Constants.GamePerformanceCounterName, out PerformanceCounter.PerformanceCounter gameExecTime)) { return gameExecTime.GetAverage(); } @@ -151,7 +151,7 @@ namespace StardewModdingAPI.Framework.Events if (!this.PerformanceCounters.ContainsKey(modName)) { - this.PerformanceCounters.Add(modName, new PerformanceCounter($"{modName}.{this.EventName}")); + this.PerformanceCounters.Add(modName, new PerformanceCounter.PerformanceCounter($"{modName}.{this.EventName}")); } this.PerformanceCounters[modName].Add(performanceCounterEntry); -- cgit 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 From fce5814bcb150c4ff105a37dfcd57f397b117e48 Mon Sep 17 00:00:00 2001 From: Drachenkaetzchen Date: Wed, 15 Jan 2020 17:43:41 +0100 Subject: Added documentation for all commands. Renamed the "monitor" command to "trigger". Method name refactoring to be more consistent. --- src/SMAPI/Framework/Events/EventManager.cs | 1 + src/SMAPI/Framework/Events/ManagedEvent.cs | 1 + 2 files changed, 2 insertions(+) (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 9c65a6cc..19a4dff8 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -174,6 +174,7 @@ namespace StardewModdingAPI.Framework.Events /// Construct an instance. /// Writes messages to the log. /// The mod registry with which to identify mods. + /// The performance counter manager. public EventManager(IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) { // create shortcut initializers diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index bba94c35..dfdd7449 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -40,6 +40,7 @@ namespace StardewModdingAPI.Framework.Events /// A human-readable name for the event. /// Writes messages to the log. /// The mod registry with which to identify mods. + /// The performance counter manager public ManagedEvent(string eventName, IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) { this.EventName = eventName; -- cgit From 22a0a32b6d959946bfd80bf0ca9796378f36e0cd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 26 Jan 2020 19:49:17 -0500 Subject: refactor performance counter code This commit performs some general refactoring, including... - avoid manually duplicating the event list; - rework the 'is important' event flag; - remove the new packages (Cyotek.Collections can be replaced with built-in types, and System.ValueTuple won't work in the Mono version used on Linux/Mac); - improve performance; - minor cleanup. --- src/SMAPI/Framework/Events/EventManager.cs | 48 +++++++++++-------- src/SMAPI/Framework/Events/IManagedEvent.cs | 10 +++- src/SMAPI/Framework/Events/ManagedEvent.cs | 71 +++++++++++++++-------------- 3 files changed, 75 insertions(+), 54 deletions(-) (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 19a4dff8..50dcc9ef 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -1,4 +1,6 @@ +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Reflection; using StardewModdingAPI.Events; using StardewModdingAPI.Framework.PerformanceCounter; @@ -174,29 +176,32 @@ namespace StardewModdingAPI.Framework.Events /// Construct an instance. /// Writes messages to the log. /// The mod registry with which to identify mods. - /// The performance counter manager. - public EventManager(IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) + /// Tracks performance metrics. + public EventManager(IMonitor monitor, ModRegistry modRegistry, PerformanceMonitor performanceMonitor) { // create shortcut initializers - ManagedEvent ManageEventOf(string typeName, string eventName) => new ManagedEvent($"{typeName}.{eventName}", monitor, modRegistry, performanceCounterManager); + ManagedEvent ManageEventOf(string typeName, string eventName, bool isPerformanceCritical = false) + { + return new ManagedEvent($"{typeName}.{eventName}", monitor, modRegistry, performanceMonitor, isPerformanceCritical); + } // init events (new) this.MenuChanged = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.MenuChanged)); - this.Rendering = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.Rendering)); - this.Rendered = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.Rendered)); - this.RenderingWorld = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingWorld)); - this.RenderedWorld = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedWorld)); - this.RenderingActiveMenu = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingActiveMenu)); - this.RenderedActiveMenu = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedActiveMenu)); - this.RenderingHud = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingHud)); - this.RenderedHud = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedHud)); + this.Rendering = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.Rendering), isPerformanceCritical: true); + this.Rendered = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.Rendered), isPerformanceCritical: true); + this.RenderingWorld = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingWorld), isPerformanceCritical: true); + this.RenderedWorld = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedWorld), isPerformanceCritical: true); + this.RenderingActiveMenu = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingActiveMenu), isPerformanceCritical: true); + this.RenderedActiveMenu = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedActiveMenu), isPerformanceCritical: true); + this.RenderingHud = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderingHud), isPerformanceCritical: true); + this.RenderedHud = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.RenderedHud), isPerformanceCritical: true); this.WindowResized = ManageEventOf(nameof(IModEvents.Display), nameof(IDisplayEvents.WindowResized)); this.GameLaunched = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.GameLaunched)); - this.UpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicking)); - this.UpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicked)); - this.OneSecondUpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicking)); - this.OneSecondUpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicked)); + this.UpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicking), isPerformanceCritical: true); + this.UpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicked), isPerformanceCritical: true); + this.OneSecondUpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicking), isPerformanceCritical: true); + this.OneSecondUpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicked), isPerformanceCritical: true); this.SaveCreating = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.SaveCreating)); this.SaveCreated = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.SaveCreated)); this.Saving = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.Saving)); @@ -209,7 +214,7 @@ namespace StardewModdingAPI.Framework.Events this.ButtonPressed = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.ButtonPressed)); this.ButtonReleased = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.ButtonReleased)); - this.CursorMoved = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.CursorMoved)); + this.CursorMoved = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.CursorMoved), isPerformanceCritical: true); this.MouseWheelScrolled = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.MouseWheelScrolled)); this.PeerContextReceived = ManageEventOf(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.PeerContextReceived)); @@ -230,8 +235,15 @@ namespace StardewModdingAPI.Framework.Events this.TerrainFeatureListChanged = ManageEventOf(nameof(IModEvents.World), nameof(IWorldEvents.TerrainFeatureListChanged)); this.LoadStageChanged = ManageEventOf(nameof(IModEvents.Specialized), nameof(ISpecializedEvents.LoadStageChanged)); - this.UnvalidatedUpdateTicking = ManageEventOf(nameof(IModEvents.Specialized), nameof(ISpecializedEvents.UnvalidatedUpdateTicking)); - this.UnvalidatedUpdateTicked = ManageEventOf(nameof(IModEvents.Specialized), nameof(ISpecializedEvents.UnvalidatedUpdateTicked)); + this.UnvalidatedUpdateTicking = ManageEventOf(nameof(IModEvents.Specialized), nameof(ISpecializedEvents.UnvalidatedUpdateTicking), isPerformanceCritical: true); + this.UnvalidatedUpdateTicked = ManageEventOf(nameof(IModEvents.Specialized), nameof(ISpecializedEvents.UnvalidatedUpdateTicked), isPerformanceCritical: true); + } + + /// Get all managed events. + public IEnumerable GetAllEvents() + { + foreach (FieldInfo field in this.GetType().GetFields()) + yield return (IManagedEvent)field.GetValue(this); } } } diff --git a/src/SMAPI/Framework/Events/IManagedEvent.cs b/src/SMAPI/Framework/Events/IManagedEvent.cs index 04476866..e4e3ca08 100644 --- a/src/SMAPI/Framework/Events/IManagedEvent.cs +++ b/src/SMAPI/Framework/Events/IManagedEvent.cs @@ -1,7 +1,15 @@ namespace StardewModdingAPI.Framework.Events { + /// Metadata for an event raised by SMAPI. internal interface IManagedEvent { - string GetName(); + /********* + ** Accessors + *********/ + /// A human-readable name for the event. + string EventName { get; } + + /// Whether the event is typically called at least once per second. + bool IsPerformanceCritical { get; } } } diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index dfdd7449..60e5c599 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using PerformanceCounterManager = StardewModdingAPI.Framework.PerformanceCounter.PerformanceCounterManager; +using StardewModdingAPI.Framework.PerformanceCounter; namespace StardewModdingAPI.Framework.Events { /// An event wrapper which intercepts and logs errors in handler code. /// The event arguments type. - internal class ManagedEvent: IManagedEvent + internal class ManagedEvent : IManagedEvent { /********* ** Fields @@ -15,9 +15,6 @@ namespace StardewModdingAPI.Framework.Events /// The underlying event. private event EventHandler Event; - /// A human-readable name for the event. - private readonly string EventName; - /// Writes messages to the log. private readonly IMonitor Monitor; @@ -30,8 +27,19 @@ namespace StardewModdingAPI.Framework.Events /// The cached invocation list. private EventHandler[] CachedInvocationList; - /// The performance counter manager. - private readonly PerformanceCounterManager PerformanceCounterManager; + /// Tracks performance metrics. + private readonly PerformanceMonitor PerformanceMonitor; + + + /********* + ** Accessors + *********/ + /// A human-readable name for the event. + public string EventName { get; } + + /// Whether the event is typically called at least once per second. + public bool IsPerformanceCritical { get; } + /********* ** Public methods @@ -40,19 +48,15 @@ namespace StardewModdingAPI.Framework.Events /// A human-readable name for the event. /// Writes messages to the log. /// The mod registry with which to identify mods. - /// The performance counter manager - public ManagedEvent(string eventName, IMonitor monitor, ModRegistry modRegistry, PerformanceCounterManager performanceCounterManager) + /// Tracks performance metrics. + /// Whether the event is typically called at least once per second. + public ManagedEvent(string eventName, IMonitor monitor, ModRegistry modRegistry, PerformanceMonitor performanceMonitor, bool isPerformanceCritical = false) { this.EventName = eventName; this.Monitor = monitor; this.ModRegistry = modRegistry; - this.PerformanceCounterManager = performanceCounterManager; - } - - /// Gets the event name. - public string GetName() - { - return this.EventName; + this.PerformanceMonitor = performanceMonitor; + this.IsPerformanceCritical = isPerformanceCritical; } /// Get whether anything is listening to the event. @@ -93,22 +97,20 @@ namespace StardewModdingAPI.Framework.Events return; - this.PerformanceCounterManager.BeginTrackInvocation(this.EventName); - - foreach (EventHandler handler in this.CachedInvocationList) + this.PerformanceMonitor.Track(this.EventName, () => { - try - { - this.PerformanceCounterManager.Track(this.EventName, this.GetModNameForPerformanceCounters(handler), - () => handler.Invoke(null, args)); - } - catch (Exception ex) + foreach (EventHandler handler in this.CachedInvocationList) { - this.LogError(handler, ex); + try + { + this.PerformanceMonitor.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. @@ -139,18 +141,17 @@ namespace StardewModdingAPI.Framework.Events /********* ** Private methods *********/ - + /// Get the mod name for a given event handler to display in performance monitoring reports. + /// The event handler. private string GetModNameForPerformanceCounters(EventHandler handler) { IModMetadata mod = this.GetSourceMod(handler); - if (mod == null) - { return Constants.GamePerformanceCounterName; - } - - return mod.HasManifest() ? mod.Manifest.UniqueID : mod.DisplayName; + return mod.HasManifest() + ? mod.Manifest.UniqueID + : mod.DisplayName; } /// Track an event handler. -- cgit From 910b4a2c4361c429b09bd35fa52d51b24cc17bc2 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 26 Jan 2020 19:52:31 -0500 Subject: tweak namespace --- src/SMAPI/Framework/Events/EventManager.cs | 2 +- src/SMAPI/Framework/Events/ManagedEvent.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Events') diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 50dcc9ef..a9dfda97 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; using StardewModdingAPI.Events; -using StardewModdingAPI.Framework.PerformanceCounter; +using StardewModdingAPI.Framework.PerformanceMonitoring; namespace StardewModdingAPI.Framework.Events { diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index 60e5c599..118b73ac 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using StardewModdingAPI.Framework.PerformanceCounter; +using StardewModdingAPI.Framework.PerformanceMonitoring; namespace StardewModdingAPI.Framework.Events { -- cgit