diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index d09bf92c8..336666704 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -211,6 +211,7 @@ namespace Dalamud { private bool isImguiDrawPluginWindow = false; private bool isImguiDrawCreditsWindow = false; private bool isImguiDrawSettingsWindow = false; + private bool isImguiDrawPluginStatWindow = false; private DalamudLogWindow logWindow; private DalamudDataWindow dataWindow; @@ -218,6 +219,7 @@ namespace Dalamud { private DalamudSettingsWindow settingsWindow; private PluginInstallerWindow pluginWindow; private ConditionDebugWindow conditionDebugWindow; + private DalamudPluginStatWindow pluginStatWindow; private void BuildDalamudUi() { @@ -294,6 +296,12 @@ namespace Dalamud { this.pluginWindow = new PluginInstallerWindow(this.PluginManager, this.PluginRepository, this.StartInfo.GameVersion); this.isImguiDrawPluginWindow = true; } + if (ImGui.MenuItem("Open Plugin Stats")) { + if (!this.isImguiDrawPluginStatWindow) { + this.pluginStatWindow = new DalamudPluginStatWindow(this.PluginManager); + this.isImguiDrawPluginStatWindow = true; + } + } if (ImGui.MenuItem("Print plugin info")) { foreach (var plugin in this.PluginManager.Plugins) { // TODO: some more here, state maybe? @@ -396,6 +404,14 @@ namespace Dalamud { { this.conditionDebugWindow.Draw(); } + + if (this.isImguiDrawPluginStatWindow) { + this.isImguiDrawPluginStatWindow = this.pluginStatWindow != null && this.pluginStatWindow.Draw(); + if (!this.isImguiDrawPluginStatWindow) { + this.pluginStatWindow?.Dispose(); + this.pluginStatWindow = null; + } + } } #endregion diff --git a/Dalamud/Interface/DalamudPluginStatWindow.cs b/Dalamud/Interface/DalamudPluginStatWindow.cs new file mode 100644 index 000000000..7862075f1 --- /dev/null +++ b/Dalamud/Interface/DalamudPluginStatWindow.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using Dalamud.Plugin; +using ImGuiNET; + +namespace Dalamud.Interface { + class DalamudPluginStatWindow : IDisposable { + + private PluginManager pm; + public DalamudPluginStatWindow(PluginManager pm) { + this.pm = pm; + } + + public bool Draw() { + bool doDraw = true; + ImGui.PushID("DalamudPluginStatWindow"); + ImGui.Begin("Plugin Statistics", ref doDraw); + ImGui.BeginTabBar("Stat Tabs"); + + if (ImGui.BeginTabItem("Draw times")) { + + bool doStats = UiBuilder.DoStats; + + if (ImGui.Checkbox("Enable Draw Time Tracking", ref doStats)) { + UiBuilder.DoStats = doStats; + } + + if (doStats) { + + ImGui.SameLine(); + if (ImGui.Button("Reset")) { + foreach (var a in this.pm.Plugins) { + a.PluginInterface.UiBuilder.lastDrawTime = -1; + a.PluginInterface.UiBuilder.maxDrawTime = -1; + a.PluginInterface.UiBuilder.drawTimeHistory.Clear(); + } + } + + + ImGui.Columns(4); + ImGui.SetColumnWidth(0, 180f); + ImGui.SetColumnWidth(1, 100f); + ImGui.SetColumnWidth(2, 100f); + ImGui.SetColumnWidth(3, 100f); + ImGui.Text("Plugin"); + ImGui.NextColumn(); + ImGui.Text("Last"); + ImGui.NextColumn(); + ImGui.Text("Longest"); + ImGui.NextColumn(); + ImGui.Text("Average"); + ImGui.NextColumn(); + ImGui.Separator(); + foreach (var a in this.pm.Plugins) { + ImGui.Text(a.Definition.Name); + ImGui.NextColumn(); + ImGui.Text($"{a.PluginInterface.UiBuilder.lastDrawTime/10000f:F4}ms"); + ImGui.NextColumn(); + ImGui.Text($"{a.PluginInterface.UiBuilder.maxDrawTime/10000f:F4}ms"); + ImGui.NextColumn(); + if (a.PluginInterface.UiBuilder.drawTimeHistory.Count > 0) { + ImGui.Text($"{a.PluginInterface.UiBuilder.drawTimeHistory.Average()/10000f:F4}ms"); + } else { + ImGui.Text("-"); + } + ImGui.NextColumn(); + } + + ImGui.Columns(1); + + } + + } + + ImGui.EndTabBar(); + + ImGui.End(); + ImGui.PopID(); + + return doDraw; + } + + public void Dispose() { + + } + } +} diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index b6e4e0914..edddc2232 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -32,6 +32,15 @@ namespace Dalamud.Interface public event RawDX11Scene.BuildUIDelegate OnBuildUi; private readonly InterfaceManager interfaceManager; + #if DEBUG + internal static bool DoStats { get; set; } = true; + #else + internal static bool DoStats { get; set; } = false; + #endif + private System.Diagnostics.Stopwatch stopwatch; + internal long lastDrawTime = -1; + internal long maxDrawTime = -1; + internal List drawTimeHistory = new List(); /// /// Create a new UiBuilder and register it. You do not have to call this manually. @@ -43,6 +52,7 @@ namespace Dalamud.Interface this.interfaceManager = interfaceManager; this.interfaceManager.OnDraw += OnDraw; + this.stopwatch = new System.Diagnostics.Stopwatch(); } /// @@ -109,6 +119,9 @@ namespace Dalamud.Interface private void OnDraw() { ImGui.PushID(this.namespaceName); + if (DoStats) { + this.stopwatch.Restart(); + } if (this.hasErrorWindow && ImGui.Begin(string.Format("{0} Error", this.namespaceName), ref this.hasErrorWindow, ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize)) { @@ -132,6 +145,13 @@ namespace Dalamud.Interface this.hasErrorWindow = true; } + if (DoStats) { + this.stopwatch.Stop(); + this.lastDrawTime = this.stopwatch.ElapsedTicks; + this.maxDrawTime = Math.Max(this.lastDrawTime, this.maxDrawTime); + this.drawTimeHistory.Add(lastDrawTime); + while (drawTimeHistory.Count > 100) drawTimeHistory.RemoveAt(0); + } ImGui.PopID(); } }