소스 검색

Use custom binary search in ValueStore.

Steven Kirk 3 년 전
부모
커밋
72308f1f37
1개의 변경된 파일27개의 추가작업 그리고 17개의 파일을 삭제
  1. 27 17
      src/Avalonia.Base/PropertyStore/ValueStore.cs

+ 27 - 17
src/Avalonia.Base/PropertyStore/ValueStore.cs

@@ -528,9 +528,8 @@ namespace Avalonia.PropertyStore
         private void InsertFrame(IValueFrame frame)
         {
             Debug.Assert(!_frames.Contains(frame));
-            var index = _frames.BinarySearch(frame, FrameInsertionComparer.Instance);
-            if (index < 0)
-                index = ~index;
+
+            var index = BinarySearchFrame(frame.Priority);
             _frames.Insert(index, frame);
             ++_frameGeneration;
             frame.SetOwner(this);
@@ -569,15 +568,12 @@ namespace Avalonia.PropertyStore
         {
             Debug.Assert(priority != BindingPriority.LocalValue);
 
-            // TODO: Binary search?
-            for (var i = _frames.Count - 1; i >= 0;  --i)
-            {
-                var frame = _frames[i];
-                if (frame is ImmediateValueFrame immediate &&  !immediate.Contains(property))
-                    return immediate;
-                if (frame.Priority > priority)
-                    break;
-            }
+            var index = BinarySearchFrame(priority);
+
+            if (index > 0 && _frames[index - 1] is ImmediateValueFrame f &&
+                f.Priority == priority &&
+                !f.Contains(property))
+                return f;
 
             var result = new ImmediateValueFrame(priority);
             InsertFrame(result);
@@ -915,14 +911,28 @@ namespace Avalonia.PropertyStore
             }
         }
 
-        private class FrameInsertionComparer : IComparer<IValueFrame>
+        private int BinarySearchFrame(BindingPriority priority)
         {
-            public static readonly FrameInsertionComparer Instance = new FrameInsertionComparer();
-            public int Compare(IValueFrame? x, IValueFrame? y)
+            var lo = 0;
+            var hi = _frames.Count - 1;
+
+            // Binary search insertion point.
+            while (lo <= hi)
             {
-                var result = y!.Priority - x!.Priority;
-                return result != 0 ? result : -1;
+                var i = lo + ((hi - lo) >> 1);
+                var order = priority - _frames[i].Priority;
+
+                if (order <= 0)
+                {
+                    lo = i + 1;
+                }
+                else
+                {
+                    hi = i - 1;
+                }
             }
+
+            return lo;
         }
 
         private readonly struct OldNewValue