Browse Source

Reduced memory traffic

Nikita Tsukanov 10 years ago
parent
commit
d1badd0dbb

+ 8 - 4
src/Perspex.Base/Threading/DispatcherTimer.cs

@@ -18,12 +18,13 @@ namespace Perspex.Threading
 
         private TimeSpan _interval;
 
+        private readonly Action _raiseTickAction;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="DispatcherTimer"/> class.
         /// </summary>
-        public DispatcherTimer()
+        public DispatcherTimer() : this(DispatcherPriority.Normal)
         {
-            _priority = DispatcherPriority.Normal;
         }
 
         /// <summary>
@@ -34,6 +35,7 @@ namespace Perspex.Threading
         public DispatcherTimer(DispatcherPriority priority)
         {
             _priority = priority;
+            _raiseTickAction = RaiseTick;
         }
 
         /// <summary>
@@ -43,7 +45,7 @@ namespace Perspex.Threading
         /// <param name="priority">The priority to use.</param>
         /// <param name="dispatcher">The dispatcher to use.</param>
         /// <param name="callback">The event to call when the timer ticks.</param>
-        public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback)
+        public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback) : this(priority)
         {
             _priority = priority;
             Interval = interval;
@@ -172,12 +174,14 @@ namespace Perspex.Threading
             }
         }
 
+        
+
         /// <summary>
         /// Raises the <see cref="Tick"/> event on the dispatcher thread.
         /// </summary>
         private void InternalTick()
         {
-            Dispatcher.UIThread.InvokeAsync(RaiseTick, _priority);
+            Dispatcher.UIThread.InvokeAsync(_raiseTickAction, _priority);
         }
 
         /// <summary>

+ 15 - 2
src/Perspex.SceneGraph/Media/DrawingContext.cs

@@ -13,8 +13,17 @@ namespace Perspex.Media
         private readonly IDrawingContextImpl _impl;
         private int _currentLevel;
 
-        private Stack<TransformContainer> _transformContainers = new Stack<TransformContainer>();
-        private Stack<PushedState> _states = new Stack<PushedState>();
+        
+
+        static readonly Stack<Stack<PushedState>> StateStackPool = new Stack<Stack<PushedState>>();
+        static readonly Stack<Stack<TransformContainer>> TransformStackPool = new Stack<Stack<TransformContainer>>();
+
+        private Stack<PushedState> _states = StateStackPool.Count == 0 ? new Stack<PushedState>() : StateStackPool.Pop();
+
+        private Stack<TransformContainer> _transformContainers = TransformStackPool.Count == 0
+            ? new Stack<TransformContainer>()
+            : TransformStackPool.Pop();
+
         struct TransformContainer
         {
             public Matrix LocalTransform;
@@ -206,6 +215,10 @@ namespace Perspex.Media
         {
             while (_states.Count != 0)
                 _states.Peek().Dispose();
+            StateStackPool.Push(_states);
+            _states = null;
+            TransformStackPool.Push(_transformContainers);
+            _transformContainers = null;
             _impl.Dispose();
         }
     }

+ 32 - 1
src/Perspex.SceneGraph/Rendering/RendererBase.cs

@@ -2,6 +2,8 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Perspex.Media;
 using Perspex.Platform;
@@ -14,6 +16,8 @@ namespace Perspex.Rendering
     /// <remarks>
     /// This class provides implements the platform-independent parts of <see cref="IRenderTarget"/>.
     /// </remarks>
+    [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")]
+    [SuppressMessage("ReSharper", "ForCanBeConvertedToForeach")]
     public static class RendererMixin
     {
         /// <summary>
@@ -58,12 +62,39 @@ namespace Perspex.Rendering
                 using (context.PushTransformContainer())
                 {
                     visual.Render(context);
-                    foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex))
+                    var lst = GetSortedVisualList(visual.VisualChildren);
+                    foreach (var child in lst)
                     {
                         context.Render(child);
                     }
+                    ReturnListToPool(lst);
                 }
             }
         }
+
+        static readonly Stack<List<IVisual>> ListPool = new Stack<List<IVisual>>();
+        static readonly ZIndexComparer VisualComparer = new ZIndexComparer();
+        class ZIndexComparer : IComparer<IVisual>
+        {
+            public int Compare(IVisual x, IVisual y) => x.ZIndex.CompareTo(y.ZIndex);
+        }
+
+        static void ReturnListToPool(List<IVisual> lst)
+        {
+            lst.Clear();
+            ListPool.Push(lst);
+        }
+
+        static List<IVisual> GetSortedVisualList(IReadOnlyList<IVisual> source)
+        {
+            var lst = ListPool.Count == 0 ? new List<IVisual>() : ListPool.Pop();
+            for (var c = 0; c < source.Count; c++)
+                lst.Add(source[c]);
+            lst.Sort(VisualComparer);
+            return lst;
+        }
+
+
+
     }
 }

+ 2 - 0
src/Skia/Perspex.Skia/FormattedTextImpl.cs

@@ -114,6 +114,8 @@ namespace Perspex.Skia
             get { return _constraint; }
             set
             {
+                if(_constraint == value)
+                    return;
                 _constraint = value;
 
                 _shared->WidthConstraint = (_constraint.Width != double.PositiveInfinity)