Przeglądaj źródła

Merge branch 'master' into IxIgnoreElementsImprovements

David Karnok 7 lat temu
rodzic
commit
3f559d97c9

+ 5 - 3
Ix.NET/Source/Benchmarks.System.Interactive/BufferCountBenchmark.cs

@@ -13,12 +13,14 @@ namespace Benchmarks.System.Interactive
     [MemoryDiagnoser]
     public class BufferCountBenchmark
     {
+        [Params(1, 10, 100, 1000, 10000, 100000, 1000000)]
+        public int N;
         private IList<int> _store;
 
         [Benchmark]
         public void Exact()
         {
-            Enumerable.Range(1, 1000)
+            Enumerable.Range(1, N)
                 .Buffer(1)
                 .Subscribe(v => Volatile.Write(ref _store, v));
         }
@@ -26,7 +28,7 @@ namespace Benchmarks.System.Interactive
         [Benchmark]
         public void Skip()
         {
-            Enumerable.Range(1, 1000)
+            Enumerable.Range(1, N)
                 .Buffer(1, 2)
                 .Subscribe(v => Volatile.Write(ref _store, v));
         }
@@ -34,7 +36,7 @@ namespace Benchmarks.System.Interactive
         [Benchmark]
         public void Overlap()
         {
-            Enumerable.Range(1, 1000)
+            Enumerable.Range(1, N)
                 .Buffer(2, 1)
                 .Subscribe(v => Volatile.Write(ref _store, v));
         }

+ 27 - 0
Ix.NET/Source/Benchmarks.System.Interactive/DeferBenchmark.cs

@@ -0,0 +1,27 @@
+// 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 DeferBenchmark
+    {
+        [Params(1, 10, 100, 1000, 10000, 100000, 1000000)]
+        public int N;
+        private int _store;
+
+        [Benchmark]
+        public void Defer()
+        {
+            EnumerableEx.Defer(() => Enumerable.Range(1, N))
+                .Subscribe(v => Volatile.Write(ref _store, v));
+        }
+    }
+}

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

@@ -19,6 +19,7 @@ namespace Benchmarks.System.Interactive
             var switcher = new BenchmarkSwitcher(new[] {
                 typeof(BufferCountBenchmark),
                 typeof(IgnoreElementsBenchmark),
+                typeof(DeferBenchmark),
             });
 
             switcher.Run();

+ 2 - 2
Ix.NET/Source/System.Interactive.Async/Catch.cs

@@ -128,7 +128,7 @@ namespace System.Linq
                                 }
                                 catch (TException ex)
                                 {
-                                    // Note: Ideally we'd dipose of the previous enumerator before
+                                    // Note: Ideally we'd dispose of the previous enumerator before
                                     // invoking the handler, but we use this order to preserve
                                     // current behavior
                                     var err = handler(ex)
@@ -253,4 +253,4 @@ namespace System.Linq
             }
         }
     }
-}
+}

+ 2 - 2
Ix.NET/Source/System.Interactive.Async/Create.cs

@@ -28,7 +28,7 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(moveNext));
             }
 
-            // Note: Many methods pass null in for the second two params. We're assuming
+            // Note: Many methods pass null in for the second two parameters. We're assuming
             // That the caller is responsible and knows what they're doing
             return new AnonymousAsyncIterator<T>(moveNext, current, dispose);
         }
@@ -128,4 +128,4 @@ namespace System.Linq
             }
         }
     }
-}
+}

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Set.cs

@@ -32,7 +32,7 @@ namespace System.Linq
         public bool Add(TElement value)
         {
 #if DEBUG
-            Debug.Assert(!_haveRemoved, "This class is optimised for never calling Add after Remove. If your changes need to do so, undo that optimization.");
+            Debug.Assert(!_haveRemoved, "This class is optimized for never calling Add after Remove. If your changes need to do so, undo that optimization.");
 #endif
             var hashCode = InternalGetHashCode(value);
             for (var i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i]._next)
@@ -99,7 +99,7 @@ namespace System.Linq
         internal TElement[] ToArray()
         {
 #if DEBUG
-            Debug.Assert(!_haveRemoved, "Optimised ToArray cannot be called if Remove has been called.");
+            Debug.Assert(!_haveRemoved, "Optimized ToArray cannot be called if Remove has been called.");
 #endif
             var array = new TElement[Count];
             for (var i = 0; i != array.Length; ++i)
@@ -113,7 +113,7 @@ namespace System.Linq
         internal List<TElement> ToList()
         {
 #if DEBUG
-            Debug.Assert(!_haveRemoved, "Optimised ToList cannot be called if Remove has been called.");
+            Debug.Assert(!_haveRemoved, "Optimized ToList cannot be called if Remove has been called.");
 #endif
             var count = Count;
             var list = new List<TElement>(count);
@@ -149,4 +149,4 @@ namespace System.Linq
             internal TElement _value;
         }
     }
-}
+}

+ 2 - 2
Ix.NET/Source/System.Interactive.Providers/QueryableEx.cs

@@ -753,7 +753,7 @@ namespace System.Linq
         /// </summary>
         /// <typeparam name="TResult">Result sequence element type.</typeparam>
         /// <param name="provider">Query provider.</param>
-        /// <param name="value">Value to repreat in the resulting sequence.</param>
+        /// <param name="value">Value to repeat in the resulting sequence.</param>
         /// <returns>Sequence repeating the given value infinitely.</returns>
         public static IEnumerable<TResult> Repeat<TResult>(this IQueryProvider provider, TResult value)
         {
@@ -1594,7 +1594,7 @@ namespace System.Linq
         /// <typeparam name="TSource">First source sequence element type.</typeparam>
         /// <typeparam name="TOther">Second source sequence element type.</typeparam>
         /// <param name="source">A sequence of values to project.</param>
-        /// <param name="other">Inner sequence each source sequenec element is projected onto.</param>
+        /// <param name="other">Inner sequence each source sequence element is projected onto.</param>
         /// <returns>Sequence flattening the sequences that result from projecting elements in the source sequence.</returns>
         public static IQueryable<TOther> SelectMany<TSource, TOther>(this IQueryable<TSource> source, IEnumerable<TOther> other)
         {

+ 68 - 2
Ix.NET/Source/System.Interactive/Buffer.cs

@@ -27,7 +27,7 @@ namespace System.Linq
                 throw new ArgumentOutOfRangeException(nameof(count));
             }
 
-            return source.Buffer_(count, count);
+            return BufferExact(source, count);
         }
 
         /// <summary>
@@ -55,6 +55,15 @@ namespace System.Linq
                 throw new ArgumentOutOfRangeException(nameof(skip));
             }
 
+            if (count == skip)
+            {
+                return BufferExact(source, count);
+            }
+            if (count < skip)
+            {
+                return BufferSkip(source, count, skip);
+            }
+
             return source.Buffer_(count, skip);
         }
 
@@ -89,6 +98,63 @@ namespace System.Linq
                 yield return buffers.Dequeue();
             }
         }
+
+        private static IEnumerable<IList<TSource>> BufferExact<TSource>(IEnumerable<TSource> source, int count)
+        {
+            IList<TSource> buffer = null;
+
+            foreach (var v in source)
+            {
+                if (buffer == null)
+                {
+                    buffer = new List<TSource>();
+                }
+
+                buffer.Add(v);
+                if (buffer.Count == count)
+                {
+                    yield return buffer;
+                    buffer = null;
+                }
+            }
+
+            if (buffer != null)
+            {
+                yield return buffer;
+            }
+        }
+
+        private static IEnumerable<IList<TSource>> BufferSkip<TSource>(IEnumerable<TSource> source, int count, int skip)
+        {
+            IList<TSource> buffer = null;
+
+            var index = 0;
+
+            foreach (var v in source)
+            {
+                if (index == 0)
+                {
+                    buffer = new List<TSource>();
+                }
+
+                buffer?.Add(v);
+                if (++index == count)
+                {
+                    yield return buffer;
+                    buffer = null;
+                }
+
+                if (index == skip)
+                {
+                    index = 0;
+                }
+            }
+
+            if (buffer != null)
+            {
+                yield return buffer;
+            }
+        }
     }
 
     /// <summary>
@@ -98,4 +164,4 @@ namespace System.Linq
     public interface IBuffer<out T> : IEnumerable<T>, IDisposable
     {
     }
-}
+}

+ 24 - 0
Ix.NET/Source/System.Interactive/Defer.cs

@@ -2,6 +2,7 @@
 // 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.Collections;
 using System.Collections.Generic;
 
 namespace System.Linq
@@ -26,10 +27,33 @@ namespace System.Linq
 
         private static IEnumerable<TSource> Defer_<TSource>(Func<IEnumerable<TSource>> enumerableFactory)
         {
+            /*
             foreach (var item in enumerableFactory())
             {
                 yield return item;
             }
+            */
+            return new DeferEnumerable<TSource>(enumerableFactory);
+        }
+
+        private sealed class DeferEnumerable<TSource> : IEnumerable<TSource>
+        {
+            readonly Func<IEnumerable<TSource>> _enumerableFactory;
+
+            public DeferEnumerable(Func<IEnumerable<TSource>> enumerableFactory)
+            {
+                _enumerableFactory = enumerableFactory;
+            }
+
+            public IEnumerator<TSource> GetEnumerator()
+            {
+                return _enumerableFactory().GetEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
         }
     }
 }

+ 2 - 2
Ix.NET/Source/System.Interactive/Repeat.cs

@@ -12,7 +12,7 @@ namespace System.Linq
         ///     Generates a sequence by repeating the given value infinitely.
         /// </summary>
         /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="value">Value to repreat in the resulting sequence.</param>
+        /// <param name="value">Value to repeat in the resulting sequence.</param>
         /// <returns>Sequence repeating the given value infinitely.</returns>
         public static IEnumerable<TResult> Repeat<TResult>(TResult value)
         {
@@ -94,4 +94,4 @@ namespace System.Linq
             }
         }
     }
-}
+}

+ 2 - 2
Ix.NET/Source/System.Interactive/SelectMany.cs

@@ -14,7 +14,7 @@ namespace System.Linq
         /// <typeparam name="TSource">First source sequence element type.</typeparam>
         /// <typeparam name="TOther">Second source sequence element type.</typeparam>
         /// <param name="source">A sequence of values to project.</param>
-        /// <param name="other">Inner sequence each source sequenec element is projected onto.</param>
+        /// <param name="other">Inner sequence each source sequence element is projected onto.</param>
         /// <returns>Sequence flattening the sequences that result from projecting elements in the source sequence.</returns>
         public static IEnumerable<TOther> SelectMany<TSource, TOther>(this IEnumerable<TSource> source, IEnumerable<TOther> other)
         {
@@ -31,4 +31,4 @@ namespace System.Linq
             return source.SelectMany(_ => other);
         }
     }
-}
+}