Переглянути джерело

Merge branch 'master' into IxRetryImprovements

David Karnok 7 роки тому
батько
коміт
5944cd8a61

+ 60 - 0
Ix.NET/Source/Benchmarks.System.Interactive/IgnoreElementsBenchmark.cs

@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using BenchmarkDotNet.Attributes;
+
+namespace Benchmarks.System.Interactive
+{
+    [MemoryDiagnoser]
+    public class IgnoreElementsBenchmark
+    {
+        [Params(1, 10, 100, 1000, 10000, 100000, 1000000)]
+        public int N;
+
+        private int _store;
+
+        private int[] _array;
+        private List<int> _list;
+
+        [Benchmark]
+        public void Ignore()
+        {
+            Enumerable.Range(1, N)
+                .IgnoreElements()
+                .Subscribe(v => Volatile.Write(ref _store, v));
+        }
+
+        [Benchmark]
+        public void IgnoreList()
+        {
+            _list
+                .IgnoreElements()
+                .Subscribe(v => Volatile.Write(ref _store, v));
+        }
+
+        [Benchmark]
+        public void IgnoreArray()
+        {
+            _array
+                .IgnoreElements()
+                .Subscribe(v => Volatile.Write(ref _store, v));
+        }
+
+        [GlobalSetup]
+        public void Setup()
+        {
+            _array = new int[N];
+            _list = new List<int>(N);
+            for (var i = 0; i < N; i++)
+            {
+                _array[i] = i;
+                _list.Add(i);
+            }
+        }
+    }
+}

+ 47 - 0
Ix.NET/Source/Benchmarks.System.Interactive/MinMaxBenchmark.cs

@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using BenchmarkDotNet.Attributes;
+
+namespace Benchmarks.System.Interactive
+{
+    [MemoryDiagnoser]
+    public class MinMaxBenchmark
+    {
+        [Params(1, 10, 100, 1000, 10000, 100000, 1000000)]
+        public int N;
+        private int _store;
+        private IList<int> _listStore;
+
+        private readonly IComparer<int> _comparer = Comparer<int>.Default;
+
+        [Benchmark]
+        public void Min()
+        {
+            Volatile.Write(ref _store, Enumerable.Range(1, N).Min(_comparer));
+        }
+
+        [Benchmark]
+        public void MinBy()
+        {
+            Volatile.Write(ref _listStore, Enumerable.Range(1, N).MinBy(v => -v, _comparer));
+        }
+
+        [Benchmark]
+        public void Max()
+        {
+            Volatile.Write(ref _store, Enumerable.Range(1, N).Max(_comparer));
+        }
+
+        [Benchmark]
+        public void MaxBy()
+        {
+            Volatile.Write(ref _listStore, Enumerable.Range(1, N).MaxBy(v => -v, _comparer));
+        }
+    }
+}

+ 2 - 0
Ix.NET/Source/Benchmarks.System.Interactive/Program.cs

@@ -18,8 +18,10 @@ namespace Benchmarks.System.Interactive
 
             var switcher = new BenchmarkSwitcher(new[] {
                 typeof(BufferCountBenchmark),
+                typeof(IgnoreElementsBenchmark),
                 typeof(DeferBenchmark),
                 typeof(RetryBenchmark),
+                typeof(MinMaxBenchmark),
             });
 
             switcher.Run();

+ 3 - 4
Ix.NET/Source/System.Interactive/IgnoreElements.cs

@@ -26,12 +26,11 @@ namespace System.Linq
 
         private static IEnumerable<TSource> IgnoreElements_<TSource>(this IEnumerable<TSource> source)
         {
-            foreach (var item in source)
+            using (var enumerator = source.GetEnumerator())
             {
-                ;
+                while (enumerator.MoveNext()) ;
             }
-
             yield break;
         }
     }
-}
+}

+ 41 - 6
Ix.NET/Source/System.Interactive/Max.cs

@@ -27,8 +27,7 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(comparer));
             }
 
-            return MaxBy(source, x => x, comparer)
-                .First();
+            return Extrema(source, x => x, comparer, 1);
         }
 
         /// <summary>
@@ -80,10 +79,46 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(comparer));
             }
 
-            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue));
+            return ExtremaBy(source, keySelector, comparer, 1);
         }
 
-        private static IList<TSource> ExtremaBy<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare)
+        private static TSource Extrema<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> compare, int direction)
+        {
+            var result = default(TSource);
+
+            using (var e = source.GetEnumerator())
+            {
+                if (!e.MoveNext())
+                {
+                    throw new InvalidOperationException("Source sequence doesn't contain any elements.");
+                }
+
+                var current = e.Current;
+                var resKey = keySelector(current);
+                result = current;
+
+                while (e.MoveNext())
+                {
+                    var cur = e.Current;
+                    var key = keySelector(cur);
+
+                    var cmp = compare.Compare(key, resKey) * direction;
+                    if (cmp == 0)
+                    {
+                        result = cur;
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = cur;
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        private static IList<TSource> ExtremaBy<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> compare, int direction)
         {
             var result = new List<TSource>();
 
@@ -103,7 +138,7 @@ namespace System.Linq
                     var cur = e.Current;
                     var key = keySelector(cur);
 
-                    var cmp = compare(key, resKey);
+                    var cmp = compare.Compare(key, resKey) * direction;
                     if (cmp == 0)
                     {
                         result.Add(cur);
@@ -122,4 +157,4 @@ namespace System.Linq
             return result;
         }
     }
-}
+}

+ 3 - 4
Ix.NET/Source/System.Interactive/Min.cs

@@ -27,8 +27,7 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(comparer));
             }
 
-            return MinBy(source, x => x, comparer)
-                .First();
+            return Extrema(source, x => x, comparer, -1);
         }
 
         /// <summary>
@@ -80,7 +79,7 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(comparer));
             }
 
-            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue));
+            return ExtremaBy(source, keySelector, comparer, -1);
         }
     }
-}
+}