From 3eb112aa682802b9d6cc71c9d243a44ceeb9d7a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Tue, 12 Jan 2021 10:42:21 +0100 Subject: [PATCH] reintroduce PerformanceMeasures for simple main cycles time measurement --- Crow/Crow.csproj | 2 +- .../{ => DebugUtils}/PerformanceMeasure.cs | 64 +++++----- Crow/src/Interface.cs | 112 +++++++++++------- Samples/PerfTests/Program.cs | 4 +- 4 files changed, 107 insertions(+), 75 deletions(-) rename Crow/src/{ => DebugUtils}/PerformanceMeasure.cs (56%) diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index 281e5729..792794aa 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -23,7 +23,7 @@ True true $(NoWarn);1591;1587;1570;1572;1573;1574 - DESIGN_MODE + DESIGN_MODE;_MEASURE_TIME false false App.config diff --git a/Crow/src/PerformanceMeasure.cs b/Crow/src/DebugUtils/PerformanceMeasure.cs similarity index 56% rename from Crow/src/PerformanceMeasure.cs rename to Crow/src/DebugUtils/PerformanceMeasure.cs index 4f489eab..f4cf76a8 100644 --- a/Crow/src/PerformanceMeasure.cs +++ b/Crow/src/DebugUtils/PerformanceMeasure.cs @@ -1,28 +1,6 @@ -// -// PerformanceMeasure.cs +// Copyright (c) 2013-2021 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2013-2017 Jean-Philippe Bruyère -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; using System.Diagnostics; @@ -38,14 +16,46 @@ namespace Crow ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value)); } #endregion + public enum Kind + { + Update, + Clipping, + Layouting, + Drawing + } + public static PerformanceMeasure[] Measures; + + [Conditional("MEASURE_TIME")] + public static void InitMeasures () { + Measures = new PerformanceMeasure[4]; + Measures[(int)Kind.Update] = new PerformanceMeasure (Kind.Update, 1); + Measures[(int)Kind.Clipping] = new PerformanceMeasure (Kind.Clipping, 1); + Measures[(int)Kind.Layouting] = new PerformanceMeasure (Kind.Layouting, 1); + Measures[(int)Kind.Drawing] = new PerformanceMeasure (Kind.Drawing, 1); + } + [Conditional ("MEASURE_TIME")] + public static void Notify () { + for (int i = 0; i < 4; i++) + Measures[i].NotifyChanges (); + } + [Conditional ("MEASURE_TIME")] + public static void Begin (Kind kind) { + Measures[(int)kind].StartCycle (); + } + [Conditional ("MEASURE_TIME")] + public static void End (Kind kind) { + Measures[(int)kind].StopCycle (); + } + public Stopwatch timer = new Stopwatch (); - public string Name; + public readonly Kind MeasureKind; public long current, minimum, maximum, total, cptMeasures; public long cancelLimit; + public string Name => MeasureKind.ToString (); - public PerformanceMeasure(string name = "unamed", long _cancelLimit = 0){ - Name = name; + public PerformanceMeasure (Kind measureKind, long _cancelLimit = 0){ + MeasureKind = measureKind; cancelLimit = _cancelLimit; ResetStats (); } diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 62380aaf..daa76b25 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -114,9 +114,14 @@ namespace Crow }; t.Start (); } + + PerformanceMeasure.InitMeasures (); } #endregion +#if MEASURE_TIME + public PerformanceMeasure[] PerfMeasures => PerformanceMeasure.Measures; +#endif /** GLFW callback may return a custom pointer, this list makes the link between the GLFW window pointer and the manage VkWindow instance. */ static Dictionary windows = new Dictionary (); @@ -723,8 +728,9 @@ namespace Crow if (!Monitor.TryEnter (UpdateMutex)) return; - + DbgLogger.StartEvent (DbgEvtType.Update); + PerformanceMeasure.Begin (PerformanceMeasure.Kind.Update); processLayouting (); @@ -736,17 +742,24 @@ namespace Crow }else processDrawing (ctx); + PerformanceMeasure.End (PerformanceMeasure.Kind.Update); DbgLogger.EndEvent (DbgEvtType.Update, true); Monitor.Exit (UpdateMutex); + + PerformanceMeasure.Notify (); } /// Layouting loop, this is the first step of the udpate and process registered /// Layouting queue items. Failing LQI's are requeued in this cycle until MaxTry is reached which /// trigger an enqueue for the next Update Cycle protected virtual void processLayouting(){ if (Monitor.TryEnter (LayoutMutex)) { - + if (LayoutingQueue.Count == 0) { + Monitor.Exit (LayoutMutex); + return; + } DbgLogger.StartEvent (DbgEvtType.Layouting); + PerformanceMeasure.Begin (PerformanceMeasure.Kind.Layouting); DiscardQueue = new Queue (); //Debug.WriteLine ("======= Layouting queue start ======="); @@ -757,6 +770,7 @@ namespace Crow } LayoutingQueue = DiscardQueue; + PerformanceMeasure.End (PerformanceMeasure.Kind.Layouting); DbgLogger.EndEvent (DbgEvtType.Layouting, true); Monitor.Exit (LayoutMutex); @@ -767,8 +781,11 @@ namespace Crow /// Clipping rectangles are added at each level of the tree from leef to root, that's the way for the painting /// operation to known if it should go down in the tree for further graphic updates and repaints void clippingRegistration(){ + if (ClippingQueue.Count == 0) + return; DbgLogger.StartEvent (DbgEvtType.Clipping); + PerformanceMeasure.Begin (PerformanceMeasure.Kind.Clipping); Widget g = null; while (ClippingQueue.Count > 0) { @@ -779,6 +796,7 @@ namespace Crow g.ClippingRegistration (); } + PerformanceMeasure.End (PerformanceMeasure.Kind.Clipping); DbgLogger.EndEvent (DbgEvtType.Clipping, true); } /// Clipping Rectangles drive the drawing process. For compositing, each object under a clip rectangle should be @@ -789,64 +807,68 @@ namespace Crow if (DragImage != null) clipping.UnionRectangle(new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight)); - if (!clipping.IsEmpty) { - IsDirty = true; - ctx.PushGroup (); + if (!clipping.IsEmpty) { + PerformanceMeasure.Begin (PerformanceMeasure.Kind.Drawing); + IsDirty = true; + + ctx.PushGroup (); - for (int i = GraphicTree.Count -1; i >= 0 ; i--){ - Widget p = GraphicTree[i]; - if (!p.Visible) - continue; - if (clipping.Contains (p.Slot) == RegionOverlap.Out) - continue; + for (int i = GraphicTree.Count -1; i >= 0 ; i--){ + Widget p = GraphicTree[i]; + if (!p.Visible) + continue; + if (clipping.Contains (p.Slot) == RegionOverlap.Out) + continue; + ctx.Save (); + p.Paint (ref ctx); + ctx.Restore (); + } + + if (DragAndDropOperation != null) { + if (DragImage != null) { + DirtyRect += new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight); + DragImageX = MousePosition.X - DragImageWidth / 2; + DragImageY = MousePosition.Y - DragImageHeight / 2; ctx.Save (); - p.Paint (ref ctx); + ctx.ResetClip (); + ctx.SetSource (DragImage, DragImageX, DragImageY); + ctx.PaintWithAlpha (0.8); ctx.Restore (); + DirtyRect += new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight); + IsDirty = true; + //System.Diagnostics.Debug.WriteLine ("dragimage drawn: {0},{1}", DragImageX, DragImageY); } - - if (DragAndDropOperation != null) { - if (DragImage != null) { - DirtyRect += new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight); - DragImageX = MousePosition.X - DragImageWidth / 2; - DragImageY = MousePosition.Y - DragImageHeight / 2; - ctx.Save (); - ctx.ResetClip (); - ctx.SetSource (DragImage, DragImageX, DragImageY); - ctx.PaintWithAlpha (0.8); - ctx.Restore (); - DirtyRect += new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight); - IsDirty = true; - //System.Diagnostics.Debug.WriteLine ("dragimage drawn: {0},{1}", DragImageX, DragImageY); - } - } + } #if DEBUG_CLIP_RECTANGLE - ctx.LineWidth = 1; - ctx.SetSourceColor(Color.Magenta.AdjustAlpha (0.5)); - for (int i = 0; i < clipping.NumRectangles; i++) - ctx.Rectangle(clipping.GetRectangle(i)); - ctx.Stroke (); + ctx.LineWidth = 1; + ctx.SetSourceColor(Color.Magenta.AdjustAlpha (0.5)); + for (int i = 0; i < clipping.NumRectangles; i++) + ctx.Rectangle(clipping.GetRectangle(i)); + ctx.Stroke (); #endif - ctx.PopGroupToSource (); + ctx.PopGroupToSource (); - for (int i = 0; i < clipping.NumRectangles; i++) - ctx.Rectangle (clipping.GetRectangle (i)); + for (int i = 0; i < clipping.NumRectangles; i++) + ctx.Rectangle (clipping.GetRectangle (i)); - ctx.ClipPreserve (); - ctx.Operator = Operator.Clear; - ctx.Fill (); - ctx.Operator = Operator.Over; + ctx.ClipPreserve (); + ctx.Operator = Operator.Clear; + ctx.Fill (); + ctx.Operator = Operator.Over; - ctx.Paint (); + ctx.Paint (); - surf.Flush (); + surf.Flush (); - clipping.Dispose (); - clipping = new Region (); - } + clipping.Dispose (); + clipping = new Region (); + + PerformanceMeasure.End (PerformanceMeasure.Kind.Drawing); + } DbgLogger.EndEvent (DbgEvtType.Drawing, true); } diff --git a/Samples/PerfTests/Program.cs b/Samples/PerfTests/Program.cs index 39ba8c88..6b239e9f 100644 --- a/Samples/PerfTests/Program.cs +++ b/Samples/PerfTests/Program.cs @@ -81,8 +81,8 @@ namespace PerfTests ClearInterface (); if (resetStylesAndTemplates) { - this.Styling.Clear (); - this.StylingConstants.Clear (); + //this.Styling.Clear (); + //this.StylingConstants.Clear (); this.Instantiators.Clear (); this.Templates.Clear (); this.DefaultTemplates.Clear (); -- 2.47.3