Browse Source

Added benchmarking stuff

Tig 9 months ago
parent
commit
bfb243a348

+ 21 - 2
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -335,8 +335,15 @@ public abstract class ConsoleDriver
                 _dirtyLines [row] = true;
                 _dirtyLines [row] = true;
             }
             }
         }
         }
+
+        ClearedContents?.Invoke (this, EventArgs.Empty);
     }
     }
 
 
+    /// <summary>
+    ///     Raised each time <see cref="ClearContents"/> is called. For benchmarking.
+    /// </summary>
+    public event EventHandler<EventArgs>? ClearedContents;
+
     /// <summary>
     /// <summary>
     /// Sets <see cref="Contents"/> as dirty for situations where views
     /// Sets <see cref="Contents"/> as dirty for situations where views
     /// don't need layout and redrawing, but just refresh the screen.
     /// don't need layout and redrawing, but just refresh the screen.
@@ -448,7 +455,18 @@ public abstract class ConsoleDriver
     public void OnSizeChanged (SizeChangedEventArgs args) { SizeChanged?.Invoke (this, args); }
     public void OnSizeChanged (SizeChangedEventArgs args) { SizeChanged?.Invoke (this, args); }
 
 
     /// <summary>Updates the screen to reflect all the changes that have been done to the display buffer</summary>
     /// <summary>Updates the screen to reflect all the changes that have been done to the display buffer</summary>
-    public abstract void Refresh ();
+    public void Refresh ()
+    {
+        bool updated = UpdateScreen ();
+        UpdateCursor ();
+
+        Refreshed?.Invoke (this, new EventArgs<bool> (in updated));
+    }
+
+    /// <summary>
+    ///     Raised each time <see cref="Refresh"/> is called. For benchmarking.
+    /// </summary>
+    public event EventHandler<EventArgs<bool>>? Refreshed;
 
 
     /// <summary>Sets the terminal cursor visibility.</summary>
     /// <summary>Sets the terminal cursor visibility.</summary>
     /// <param name="visibility">The wished <see cref="CursorVisibility"/></param>
     /// <param name="visibility">The wished <see cref="CursorVisibility"/></param>
@@ -466,7 +484,8 @@ public abstract class ConsoleDriver
     public abstract void UpdateCursor ();
     public abstract void UpdateCursor ();
 
 
     /// <summary>Redraws the physical screen with the contents that have been queued up via any of the printing commands.</summary>
     /// <summary>Redraws the physical screen with the contents that have been queued up via any of the printing commands.</summary>
-    public abstract void UpdateScreen ();
+    /// <returns><see langword="true"/> if any updates to the screen were made.</returns>
+    public abstract bool UpdateScreen ();
 
 
     #region Setup & Teardown
     #region Setup & Teardown
 
 

+ 9 - 10
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -105,12 +105,7 @@ internal class CursesDriver : ConsoleDriver
         }
         }
     }
     }
 
 
-    public override void Refresh ()
-    {
-        UpdateScreen ();
-        UpdateCursor ();
-    }
-
+    
     public override void SendKeys (char keyChar, ConsoleKey consoleKey, bool shift, bool alt, bool control)
     public override void SendKeys (char keyChar, ConsoleKey consoleKey, bool shift, bool alt, bool control)
     {
     {
         KeyCode key;
         KeyCode key;
@@ -228,8 +223,9 @@ internal class CursesDriver : ConsoleDriver
         }
         }
     }
     }
 
 
-    public override void UpdateScreen ()
+    public override bool UpdateScreen ()
     {
     {
+        bool updated = false;
         if (Force16Colors)
         if (Force16Colors)
         {
         {
             for (var row = 0; row < Rows; row++)
             for (var row = 0; row < Rows; row++)
@@ -297,7 +293,7 @@ internal class CursesDriver : ConsoleDriver
                 || Contents.Length != Rows * Cols
                 || Contents.Length != Rows * Cols
                 || Rows != Console.WindowHeight)
                 || Rows != Console.WindowHeight)
             {
             {
-                return;
+                return updated;
             }
             }
 
 
             var top = 0;
             var top = 0;
@@ -315,7 +311,7 @@ internal class CursesDriver : ConsoleDriver
             {
             {
                 if (Console.WindowHeight < 1)
                 if (Console.WindowHeight < 1)
                 {
                 {
-                    return;
+                    return updated;
                 }
                 }
 
 
                 if (!_dirtyLines [row])
                 if (!_dirtyLines [row])
@@ -325,7 +321,7 @@ internal class CursesDriver : ConsoleDriver
 
 
                 if (!SetCursorPosition (0, row))
                 if (!SetCursorPosition (0, row))
                 {
                 {
-                    return;
+                    return updated;
                 }
                 }
 
 
                 _dirtyLines [row] = false;
                 _dirtyLines [row] = false;
@@ -338,6 +334,7 @@ internal class CursesDriver : ConsoleDriver
 
 
                     for (; col < cols; col++)
                     for (; col < cols; col++)
                     {
                     {
+                        updated = true;
                         if (!Contents [row, col].IsDirty)
                         if (!Contents [row, col].IsDirty)
                         {
                         {
                             if (output.Length > 0)
                             if (output.Length > 0)
@@ -433,6 +430,8 @@ internal class CursesDriver : ConsoleDriver
                 outputWidth = 0;
                 outputWidth = 0;
             }
             }
         }
         }
+
+        return updated;
     }
     }
 
 
     private bool SetCursorPosition (int col, int row)
     private bool SetCursorPosition (int col, int row)

+ 6 - 6
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -101,8 +101,10 @@ public class FakeDriver : ConsoleDriver
         return new MainLoop (_mainLoopDriver);
         return new MainLoop (_mainLoopDriver);
     }
     }
 
 
-    public override void UpdateScreen ()
+    public override bool UpdateScreen ()
     {
     {
+        bool updated = false;
+
         int savedRow = FakeConsole.CursorTop;
         int savedRow = FakeConsole.CursorTop;
         int savedCol = FakeConsole.CursorLeft;
         int savedCol = FakeConsole.CursorLeft;
         bool savedCursorVisible = FakeConsole.CursorVisible;
         bool savedCursorVisible = FakeConsole.CursorVisible;
@@ -122,6 +124,8 @@ public class FakeDriver : ConsoleDriver
                 continue;
                 continue;
             }
             }
 
 
+            updated = true;
+
             FakeConsole.CursorTop = row;
             FakeConsole.CursorTop = row;
             FakeConsole.CursorLeft = 0;
             FakeConsole.CursorLeft = 0;
 
 
@@ -218,13 +222,9 @@ public class FakeDriver : ConsoleDriver
         FakeConsole.CursorTop = savedRow;
         FakeConsole.CursorTop = savedRow;
         FakeConsole.CursorLeft = savedCol;
         FakeConsole.CursorLeft = savedCol;
         FakeConsole.CursorVisible = savedCursorVisible;
         FakeConsole.CursorVisible = savedCursorVisible;
+        return updated;
     }
     }
 
 
-    public override void Refresh ()
-    {
-        UpdateScreen ();
-        UpdateCursor ();
-    }
 
 
     #region Color Handling
     #region Color Handling
 
 

+ 8 - 10
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -823,12 +823,6 @@ internal class NetDriver : ConsoleDriver
     public override bool SupportsTrueColor => Environment.OSVersion.Platform == PlatformID.Unix
     public override bool SupportsTrueColor => Environment.OSVersion.Platform == PlatformID.Unix
                                               || (IsWinPlatform && Environment.OSVersion.Version.Build >= 14931);
                                               || (IsWinPlatform && Environment.OSVersion.Version.Build >= 14931);
 
 
-    public override void Refresh ()
-    {
-        UpdateScreen ();
-        UpdateCursor ();
-    }
-
     public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
     public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
     {
     {
         var input = new InputResult
         var input = new InputResult
@@ -876,15 +870,16 @@ internal class NetDriver : ConsoleDriver
         StartReportingMouseMoves ();
         StartReportingMouseMoves ();
     }
     }
 
 
-    public override void UpdateScreen ()
+    public override bool UpdateScreen ()
     {
     {
+        bool updated = false;
         if (RunningUnitTests
         if (RunningUnitTests
             || _winSizeChanging
             || _winSizeChanging
             || Console.WindowHeight < 1
             || Console.WindowHeight < 1
             || Contents.Length != Rows * Cols
             || Contents.Length != Rows * Cols
             || Rows != Console.WindowHeight)
             || Rows != Console.WindowHeight)
         {
         {
-            return;
+            return updated;
         }
         }
 
 
         var top = 0;
         var top = 0;
@@ -902,7 +897,7 @@ internal class NetDriver : ConsoleDriver
         {
         {
             if (Console.WindowHeight < 1)
             if (Console.WindowHeight < 1)
             {
             {
-                return;
+                return updated;
             }
             }
 
 
             if (!_dirtyLines [row])
             if (!_dirtyLines [row])
@@ -912,9 +907,10 @@ internal class NetDriver : ConsoleDriver
 
 
             if (!SetCursorPosition (0, row))
             if (!SetCursorPosition (0, row))
             {
             {
-                return;
+                return updated;
             }
             }
 
 
+            updated = true;
             _dirtyLines [row] = false;
             _dirtyLines [row] = false;
             output.Clear ();
             output.Clear ();
 
 
@@ -1034,6 +1030,8 @@ internal class NetDriver : ConsoleDriver
             lastCol += outputWidth;
             lastCol += outputWidth;
             outputWidth = 0;
             outputWidth = 0;
         }
         }
+
+        return updated;
     }
     }
 
 
     internal override void End ()
     internal override void End ()

+ 6 - 9
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1085,13 +1085,6 @@ internal class WindowsDriver : ConsoleDriver
 
 
     public override bool IsRuneSupported (Rune rune) { return base.IsRuneSupported (rune) && rune.IsBmp; }
     public override bool IsRuneSupported (Rune rune) { return base.IsRuneSupported (rune) && rune.IsBmp; }
 
 
-    public override void Refresh ()
-    {
-        UpdateScreen ();
-        //WinConsole?.SetInitialCursorVisibility ();
-        UpdateCursor ();
-    }
-
     public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
     public override void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
     {
     {
         var input = new WindowsConsole.InputRecord
         var input = new WindowsConsole.InputRecord
@@ -1284,13 +1277,14 @@ internal class WindowsDriver : ConsoleDriver
 
 
     #endregion Cursor Handling
     #endregion Cursor Handling
 
 
-    public override void UpdateScreen ()
+    public override bool UpdateScreen ()
     {
     {
+        bool updated = false;
         Size windowSize = WinConsole?.GetConsoleBufferWindow (out Point _) ?? new Size (Cols, Rows);
         Size windowSize = WinConsole?.GetConsoleBufferWindow (out Point _) ?? new Size (Cols, Rows);
 
 
         if (!windowSize.IsEmpty && (windowSize.Width != Cols || windowSize.Height != Rows))
         if (!windowSize.IsEmpty && (windowSize.Width != Cols || windowSize.Height != Rows))
         {
         {
-            return;
+            return updated;
         }
         }
 
 
         var bufferCoords = new WindowsConsole.Coord
         var bufferCoords = new WindowsConsole.Coord
@@ -1307,6 +1301,7 @@ internal class WindowsDriver : ConsoleDriver
             }
             }
 
 
             _dirtyLines [row] = false;
             _dirtyLines [row] = false;
+            updated = true;
 
 
             for (var col = 0; col < Cols; col++)
             for (var col = 0; col < Cols; col++)
             {
             {
@@ -1365,6 +1360,8 @@ internal class WindowsDriver : ConsoleDriver
         }
         }
 
 
         WindowsConsole.SmallRect.MakeEmpty (ref _damageRegion);
         WindowsConsole.SmallRect.MakeEmpty (ref _damageRegion);
+
+        return updated;
     }
     }
 
 
     internal override void End ()
     internal override void End ()

+ 3 - 15
UICatalog/Scenarios/Generic.cs

@@ -4,7 +4,7 @@ namespace UICatalog.Scenarios;
 
 
 [ScenarioMetadata ("Generic", "Generic sample - A template for creating new Scenarios")]
 [ScenarioMetadata ("Generic", "Generic sample - A template for creating new Scenarios")]
 [ScenarioCategory ("Controls")]
 [ScenarioCategory ("Controls")]
-public sealed class MyScenario : Scenario
+public sealed class Generic : Scenario
 {
 {
     public override void Main ()
     public override void Main ()
     {
     {
@@ -14,24 +14,12 @@ public sealed class MyScenario : Scenario
         // Setup - Create a top-level application window and configure it.
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         Window appWindow = new ()
         {
         {
-            Id = "appWindow",
             Title = GetQuitKeyAndName (),
             Title = GetQuitKeyAndName (),
-            Arrangement = ViewArrangement.Fixed
         };
         };
 
 
-        var button = new Button
-        {
-            Id = "button",
-            X = Pos.AnchorEnd(), Y = 0, Text = "_Press me!"
-        };
+        var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "_Press me!" };
         button.Accepting += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "_Ok");
         button.Accepting += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "_Ok");
-
-        button.HighlightStyle = HighlightStyle.None;
-        button.ShadowStyle = ShadowStyle.None;
-
-        appWindow.Border.Add (button);
-
-        //appWindow.Border.LineStyle = LineStyle.None;
+        appWindow.Add (button);
 
 
         // Run - Start the application.
         // Run - Start the application.
         Application.Run (appWindow);
         Application.Run (appWindow);

+ 89 - 2
UnitTests/UICatalog/ScenarioTests.cs

@@ -93,13 +93,13 @@ public class ScenarioTests : TestsAllViews
                     timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
                     timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
                 }
                 }
 
 
-                _output.WriteLine ($"Initialized '{Application.Driver}'");
             }
             }
             else
             else
             {
             {
                 Application.Iteration -= OnApplicationOnIteration;
                 Application.Iteration -= OnApplicationOnIteration;
                 shutdown = true;
                 shutdown = true;
             }
             }
+            _output.WriteLine ($"Initialized == {a.CurrentValue}");
         }
         }
 
 
         // If the scenario doesn't close within 500ms, this will force it to quit
         // If the scenario doesn't close within 500ms, this will force it to quit
@@ -131,12 +131,99 @@ public class ScenarioTests : TestsAllViews
             if (Application.IsInitialized)
             if (Application.IsInitialized)
             {
             {
                 // Press QuitKey 
                 // Press QuitKey 
-                //_output.WriteLine ($"Forcing Quit with {Application.QuitKey}");
+                _output.WriteLine ($"Attempting to quit with {Application.QuitKey}");
                 Application.RaiseKeyDownEvent (Application.QuitKey);
                 Application.RaiseKeyDownEvent (Application.QuitKey);
             }
             }
         }
         }
     }
     }
 
 
+
+    /// <summary>
+    ///     <para>This runs through all Scenarios defined in UI Catalog, calling Init, Setup, and Run and measuring the perf of each.</para>
+    /// </summary>
+    [Theory]
+    [MemberData (nameof (AllScenarioTypes))]
+    public void All_Scenarios_Time (Type scenarioType)
+    {
+        // Disable any UIConfig settings
+        ConfigurationManager.ConfigLocations savedConfigLocations = ConfigurationManager.Locations;
+        ConfigurationManager.Locations = ConfigurationManager.ConfigLocations.DefaultOnly;
+
+        // If a previous test failed, this will ensure that the Application is in a clean state
+        Application.ResetState (true);
+
+        int iterationCount = 0;
+
+        int clearedContentCount = 0;
+        int refreshedCount = 0;
+        int updatedCount = 0;
+
+        _output.WriteLine ($"Running Scenario '{scenarioType}'");
+        var scenario = (Scenario)Activator.CreateInstance (scenarioType);
+
+        Stopwatch stopwatch = null;
+
+        Application.InitializedChanged += OnApplicationOnInitializedChanged;
+
+        Application.ForceDriver = "FakeDriver";
+        scenario!.Main ();
+        scenario.Dispose ();
+        scenario = null;
+        Application.ForceDriver = string.Empty;
+
+        Application.InitializedChanged -= OnApplicationOnInitializedChanged;
+
+        _output.WriteLine ($"Scenario {scenarioType}");
+        _output.WriteLine ($"  took {stopwatch.ElapsedMilliseconds} ms to run.");
+        _output.WriteLine ($"  called Driver.ClearContents {clearedContentCount} times.");
+        _output.WriteLine ($"  called Driver.Refresh {refreshedCount} times.");
+        _output.WriteLine ($"    which updated the screen {updatedCount} times.");
+
+        // Restore the configuration locations
+        ConfigurationManager.Locations = savedConfigLocations;
+        ConfigurationManager.Reset ();
+
+        return;
+
+        void OnApplicationOnInitializedChanged (object s, EventArgs<bool> a)
+        {
+            if (a.CurrentValue)
+            {
+                Application.Iteration += OnApplicationOnIteration;
+                Application.Driver!.ClearedContents += (sender, args) => clearedContentCount++;
+                Application.Driver!.Refreshed += (sender, args) =>
+                                                 {
+                                                     refreshedCount++;
+
+                                                     if (args.CurrentValue)
+                                                     {
+                                                         updatedCount++;
+                                                     }
+                                                 };
+
+                stopwatch = Stopwatch.StartNew ();
+            }
+            else
+            {
+                Application.Iteration -= OnApplicationOnIteration;
+                stopwatch!.Stop ();
+            }
+            _output.WriteLine ($"Initialized == {a.CurrentValue}");
+        }
+
+        void OnApplicationOnIteration (object s, IterationEventArgs a)
+        {
+            iterationCount++;
+            if (iterationCount > 5000)
+            {
+                // Press QuitKey
+                _output.WriteLine ($"Attempting to quit with {Application.QuitKey}");
+                Application.RaiseKeyDownEvent (Application.QuitKey);
+            }
+        }
+    }
+
+
     public static IEnumerable<object []> AllScenarioTypes =>
     public static IEnumerable<object []> AllScenarioTypes =>
         typeof (Scenario).Assembly
         typeof (Scenario).Assembly
                          .GetTypes ()
                          .GetTypes ()