]> O.S.I.I.S - jp/crow.git/commitdiff
reintroduce PerformanceMeasures for simple main cycles time measurement
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 12 Jan 2021 09:42:21 +0000 (10:42 +0100)
committerj-p <jp_bruyere@hotmail.com>
Sat, 6 Feb 2021 19:28:02 +0000 (20:28 +0100)
Crow/Crow.csproj
Crow/src/DebugUtils/PerformanceMeasure.cs [new file with mode: 0644]
Crow/src/Interface.cs
Crow/src/PerformanceMeasure.cs [deleted file]
Samples/PerfTests/Program.cs

index 281e572900ade950154de3c356659052df503431..792794aa49d63cbe11f46e968d4af9a49f337298 100644 (file)
@@ -23,7 +23,7 @@
                <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
                <GenerateDocumentationFile>true</GenerateDocumentationFile>
                <NoWarn>$(NoWarn);1591;1587;1570;1572;1573;1574</NoWarn>
-               <DefineConstants>DESIGN_MODE</DefineConstants>          
+               <DefineConstants>DESIGN_MODE;_MEASURE_TIME</DefineConstants>            
                <EnableDefaultItems>false</EnableDefaultItems>
                <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
                <AppConfig>App.config</AppConfig>
diff --git a/Crow/src/DebugUtils/PerformanceMeasure.cs b/Crow/src/DebugUtils/PerformanceMeasure.cs
new file mode 100644 (file)
index 0000000..f4cf76a
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright (c) 2013-2021  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Diagnostics;
+
+namespace Crow
+{
+       public class PerformanceMeasure : IValueChange {
+               #region IValueChange implementation
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               public virtual void NotifyValueChanged(string MemberName, object _value)
+               {
+                       if (ValueChanged != null)                               
+                               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 readonly Kind MeasureKind;
+               public long current, minimum, maximum, total, cptMeasures;
+               public long cancelLimit;
+               public string Name => MeasureKind.ToString ();
+
+               public PerformanceMeasure (Kind measureKind, long _cancelLimit = 0){
+                       MeasureKind = measureKind;
+                       cancelLimit = _cancelLimit;
+                       ResetStats ();
+               }
+
+               public void StartCycle(){
+                       timer.Restart();
+               }
+               public void StopCycle(){
+                       timer.Stop();
+                       computeStats ();
+               }
+               public void NotifyChanges(){
+                       lock(this){
+                               if (cptMeasures == 0)
+                                       return;
+                               NotifyValueChanged("minimum", minimum);
+                               NotifyValueChanged("maximum", maximum);
+                               NotifyValueChanged("current", current);
+                               //                      NotifyValueChanged("total", total);
+                               //                      NotifyValueChanged("cptMeasures", cptMeasures);
+                               NotifyValueChanged("mean", total / cptMeasures);
+                       }
+               }
+
+               void computeStats(){                    
+                       current = timer.ElapsedMilliseconds;
+                       if (current < cancelLimit)
+                               return;
+                       cptMeasures++;
+                       total += timer.ElapsedMilliseconds;
+                       if (timer.ElapsedMilliseconds < minimum)
+                               minimum = timer.ElapsedMilliseconds;
+                       if (timer.ElapsedMilliseconds > maximum)
+                               maximum = timer.ElapsedMilliseconds;                    
+               }
+               void ResetStats(){
+                       Debug.WriteLine("reset measure cpt:{0}",cptMeasures);
+                       cptMeasures = total = current = maximum = 0;
+                       minimum = long.MaxValue;
+               }
+               void onResetClick(object sender, MouseButtonEventArgs e){
+                       lock(this)
+                               ResetStats();
+               }
+       }
+}
+
index 62380aaf6d35cd8a42bb8755297479983b535cc0..daa76b257600e0799d83cfeb7619bebc1c2f4238 100644 (file)
@@ -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<IntPtr, Interface> windows = new Dictionary<IntPtr, Interface> ();
@@ -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 ();
                }
                /// <summary>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</summary>
                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<LayoutingQueueItem> ();
                                //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</summary>
                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);
                }
                /// <summary>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/Crow/src/PerformanceMeasure.cs b/Crow/src/PerformanceMeasure.cs
deleted file mode 100644 (file)
index 4f489ea..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// PerformanceMeasure.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// 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.
-
-using System;
-using System.Diagnostics;
-
-namespace Crow
-{
-       public class PerformanceMeasure : IValueChange {
-               #region IValueChange implementation
-               public event EventHandler<ValueChangeEventArgs> ValueChanged;
-               public virtual void NotifyValueChanged(string MemberName, object _value)
-               {
-                       if (ValueChanged != null)                               
-                               ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
-               }
-               #endregion
-
-               public Stopwatch timer = new Stopwatch ();
-               public string Name;
-               public long current, minimum, maximum, total, cptMeasures;
-               public long cancelLimit;
-
-               public PerformanceMeasure(string name = "unamed", long _cancelLimit = 0){
-                       Name = name;
-                       cancelLimit = _cancelLimit;
-                       ResetStats ();
-               }
-
-               public void StartCycle(){
-                       timer.Restart();
-               }
-               public void StopCycle(){
-                       timer.Stop();
-                       computeStats ();
-               }
-               public void NotifyChanges(){
-                       lock(this){
-                               if (cptMeasures == 0)
-                                       return;
-                               NotifyValueChanged("minimum", minimum);
-                               NotifyValueChanged("maximum", maximum);
-                               NotifyValueChanged("current", current);
-                               //                      NotifyValueChanged("total", total);
-                               //                      NotifyValueChanged("cptMeasures", cptMeasures);
-                               NotifyValueChanged("mean", total / cptMeasures);
-                       }
-               }
-
-               void computeStats(){                    
-                       current = timer.ElapsedMilliseconds;
-                       if (current < cancelLimit)
-                               return;
-                       cptMeasures++;
-                       total += timer.ElapsedMilliseconds;
-                       if (timer.ElapsedMilliseconds < minimum)
-                               minimum = timer.ElapsedMilliseconds;
-                       if (timer.ElapsedMilliseconds > maximum)
-                               maximum = timer.ElapsedMilliseconds;                    
-               }
-               void ResetStats(){
-                       Debug.WriteLine("reset measure cpt:{0}",cptMeasures);
-                       cptMeasures = total = current = maximum = 0;
-                       minimum = long.MaxValue;
-               }
-               void onResetClick(object sender, MouseButtonEventArgs e){
-                       lock(this)
-                               ResetStats();
-               }
-       }
-}
-
index 39ba8c88bf70b8ba2da42e8e7ae688475e19aa94..6b239e9ff952a0cee9b30ef0cd02e9c203101370 100644 (file)
@@ -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 ();