瀏覽代碼

Adding a perf suite to compare interface designs.

Bart De Smet 8 年之前
父節點
當前提交
e762b9295d
共有 3 個文件被更改,包括 1597 次插入0 次删除
  1. 8 0
      Ix.NET/Source/FasterLinq/FasterLinq.csproj
  2. 1570 0
      Ix.NET/Source/FasterLinq/Program.cs
  3. 19 0
      Ix.NET/Source/Ix.NET.sln

+ 8 - 0
Ix.NET/Source/FasterLinq/FasterLinq.csproj

@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp1.1</TargetFramework>
+  </PropertyGroup>
+
+</Project>

+ 1570 - 0
Ix.NET/Source/FasterLinq/Program.cs

@@ -0,0 +1,1570 @@
+// 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;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Labs.Linq;
+using System.Threading.Tasks;
+
+namespace FasterLinq
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            var N = 4;
+
+            Sync(N);
+            Async1(N).Wait();
+            Async2(N).Wait();
+        }
+
+        static void Sync(int n)
+        {
+            Console.WriteLine("IEnumerable<T> and IFastEnumerable<T>");
+            Console.WriteLine();
+
+            var sw = new Stopwatch();
+
+            var N = 10_000_000;
+
+            var next = new Action<int>(_ => { });
+
+            var slowRange = Enumerable.Range(0, N);
+            var fastRange = FastEnumerable.Range(0, N);
+            var brdgRange = slowRange.ToFastEnumerable();
+
+            var slow = slowRange.Where(x => x % 2 == 0).Select(x => x + 1);
+            var fast = fastRange.Where(x => x % 2 == 0).Select(x => x + 1);
+            var brdg = brdgRange.Where(x => x % 2 == 0).Select(x => x + 1).ToEnumerable();
+
+            Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x));
+            Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x));
+            Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x));
+            Console.WriteLine();
+
+            for (var i = 0; i < n; i++)
+            {
+                sw.Restart();
+                {
+                    slow.ForEach(next);
+                }
+                Console.WriteLine("SLOW " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    fast.ForEach(next);
+                }
+                Console.WriteLine("FAST " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    brdg.ForEach(next);
+                }
+                Console.WriteLine("BRDG " + sw.Elapsed);
+
+                Console.WriteLine();
+            }
+
+            Console.WriteLine();
+        }
+
+        static async Task Async1(int n)
+        {
+            Console.WriteLine("IAsyncEnumerable<T> and IAsyncFastEnumerable<T> - Synchronous query operators");
+            Console.WriteLine();
+
+            var sw = new Stopwatch();
+
+            var N = 10_000_000;
+
+            var next = new Func<int, Task>(_ => Task.CompletedTask);
+
+            var slowRange = AsyncEnumerable.Range(0, N);
+            var fastRange = AsyncFastEnumerable.Range(0, N);
+            var brdgRange = slowRange.ToAsyncFastEnumerable();
+
+            var slow = slowRange.Where(x => x % 2 == 0).Select(x => x + 1);
+            var fast = fastRange.Where(x => x % 2 == 0).Select(x => x + 1);
+            var brdg = brdgRange.Where(x => x % 2 == 0).Select(x => x + 1).ToAsyncEnumerable();
+
+            Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine();
+
+            for (var i = 0; i < n; i++)
+            {
+                sw.Restart();
+                {
+                    await slow.ForEachAsync(next);
+                }
+                Console.WriteLine("SLOW " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    await fast.ForEachAsync(next);
+                }
+                Console.WriteLine("FAST " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    await brdg.ForEachAsync(next);
+                }
+                Console.WriteLine("BRDG " + sw.Elapsed);
+
+                Console.WriteLine();
+            }
+
+            Console.WriteLine();
+        }
+
+        static async Task Async2(int n)
+        {
+            Console.WriteLine("IAsyncEnumerable<T> and IAsyncFastEnumerable<T> - Asynchronous query operators");
+            Console.WriteLine();
+
+            var sw = new Stopwatch();
+
+            var N = 10_000_000;
+
+            var next = new Func<int, Task>(_ => Task.CompletedTask);
+
+            var slowRange = AsyncEnumerable.Range(0, N);
+            var fastRange = AsyncFastEnumerable.Range(0, N);
+            var brdgRange = slowRange.ToAsyncFastEnumerable();
+
+            var slow = slowRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1));
+            var fast = fastRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1));
+            var brdg = brdgRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1)).ToAsyncEnumerable();
+
+            Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x).Result);
+            Console.WriteLine();
+
+            for (var i = 0; i < n; i++)
+            {
+                sw.Restart();
+                {
+                    await slow.ForEachAsync(next);
+                }
+                Console.WriteLine("SLOW " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    await fast.ForEachAsync(next);
+                }
+                Console.WriteLine("FAST " + sw.Elapsed);
+
+                sw.Restart();
+                {
+                    await brdg.ForEachAsync(next);
+                }
+                Console.WriteLine("BRDG " + sw.Elapsed);
+
+                Console.WriteLine();
+            }
+
+            Console.WriteLine();
+        }
+    }
+}
+
+namespace System
+{
+    public interface IAsyncDisposable
+    {
+        Task DisposeAsync();
+    }
+}
+
+namespace System.Collections.Generic
+{
+    public interface IAsyncEnumerable<out T>
+    {
+        IAsyncEnumerator<T> GetAsyncEnumerator();
+    }
+
+    public interface IAsyncEnumerator<out T> : IAsyncDisposable
+    {
+        Task<bool> MoveNextAsync();
+        T Current { get; }
+    }
+
+    public interface IFastEnumerable<out T>
+    {
+        IFastEnumerator<T> GetEnumerator();
+    }
+
+    public interface IFastEnumerator<out T> : IDisposable
+    {
+        T TryGetNext(out bool success);
+    }
+
+    public interface IAsyncFastEnumerable<out T>
+    {
+        IAsyncFastEnumerator<T> GetAsyncEnumerator();
+    }
+
+    public interface IAsyncFastEnumerator<out T> : IAsyncDisposable
+    {
+        Task<bool> WaitForNextAsync();
+        T TryGetNext(out bool success);
+    }
+}
+
+namespace System.Labs.Linq
+{
+    internal abstract class Iterator<T> : IEnumerable<T>, IEnumerator<T>
+    {
+        private readonly int _threadId;
+        internal int _state;
+        protected T _current;
+
+        protected Iterator()
+        {
+            _threadId = Environment.CurrentManagedThreadId;
+        }
+
+        public abstract Iterator<T> Clone();
+
+        public virtual void Dispose()
+        {
+            _state = -1;
+        }
+
+        public IEnumerator<T> GetEnumerator()
+        {
+            Iterator<T> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone();
+            enumerator._state = 1;
+            return enumerator;
+        }
+
+        public abstract bool MoveNext();
+
+        public T Current => _current;
+
+        object IEnumerator.Current => _current;
+
+        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+        public void Reset() => throw new NotSupportedException();
+    }
+
+    internal abstract class AsyncIterator<T> : IAsyncEnumerable<T>, IAsyncEnumerator<T>
+    {
+        private readonly int _threadId;
+        internal int _state;
+        protected T _current;
+
+        protected AsyncIterator()
+        {
+            _threadId = Environment.CurrentManagedThreadId;
+        }
+
+        public abstract AsyncIterator<T> Clone();
+
+        public virtual Task DisposeAsync()
+        {
+            _state = -1;
+            return Task.CompletedTask;
+        }
+
+        public IAsyncEnumerator<T> GetAsyncEnumerator()
+        {
+            AsyncIterator<T> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone();
+            enumerator._state = 1;
+            return enumerator;
+        }
+
+        public abstract Task<bool> MoveNextAsync();
+
+        public T Current => _current;
+    }
+
+    internal abstract class FastIterator<T> : IFastEnumerable<T>, IFastEnumerator<T>
+    {
+        private readonly int _threadId;
+        internal int _state;
+
+        protected FastIterator()
+        {
+            _threadId = Environment.CurrentManagedThreadId;
+        }
+
+        public abstract FastIterator<T> Clone();
+
+        public virtual void Dispose()
+        {
+            _state = -1;
+        }
+
+        public IFastEnumerator<T> GetEnumerator()
+        {
+            FastIterator<T> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone();
+            enumerator._state = 1;
+            return enumerator;
+        }
+
+        public abstract T TryGetNext(out bool success);
+    }
+
+    internal abstract class AsyncFastIterator<T> : IAsyncFastEnumerable<T>, IAsyncFastEnumerator<T>
+    {
+        private readonly int _threadId;
+        internal int _state;
+
+        protected AsyncFastIterator()
+        {
+            _threadId = Environment.CurrentManagedThreadId;
+        }
+
+        public abstract AsyncFastIterator<T> Clone();
+
+        public virtual Task DisposeAsync()
+        {
+            _state = -1;
+            return Task.CompletedTask;
+        }
+
+        public IAsyncFastEnumerator<T> GetAsyncEnumerator()
+        {
+            AsyncFastIterator<T> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone();
+            enumerator._state = 1;
+            return enumerator;
+        }
+
+        public abstract Task<bool> WaitForNextAsync();
+
+        public abstract T TryGetNext(out bool success);
+    }
+
+    public static class Enumerable
+    {
+        public static R Aggregate<T, R>(this IEnumerable<T> source, R seed, Func<R, T, R> aggregate)
+        {
+            var res = seed;
+
+            foreach (var item in source)
+            {
+                res = aggregate(res, item);
+            }
+
+            return res;
+        }
+
+        public static IEnumerable<T> Empty<T>() => EmptyIterator<T>.Instance;
+
+        public static void ForEach<T>(this IEnumerable<T> source, Action<T> next)
+        {
+            foreach (var item in source)
+            {
+                next(item);
+            }
+        }
+
+        public static IEnumerable<int> Range(int start, int count) => new RangeIterator(start, count);
+
+        public static IEnumerable<R> Select<T, R>(this IEnumerable<T> source, Func<T, R> selector) => new SelectIterator<T, R>(source, selector);
+
+        public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) => new WhereIterator<T>(source, predicate);
+
+        private sealed class EmptyIterator<T> : IEnumerable<T>, IEnumerator<T>
+        {
+            public static readonly EmptyIterator<T> Instance = new EmptyIterator<T>();
+
+            public T Current => default(T);
+
+            object IEnumerator.Current => default(T);
+
+            public void Dispose() { }
+
+            public IEnumerator<T> GetEnumerator() => this;
+
+            public bool MoveNext() => false;
+
+            public void Reset() { }
+
+            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+        }
+
+        private sealed class RangeIterator : Iterator<int>
+        {
+            private readonly int _start;
+            private readonly int _end;
+            private int _next;
+
+            public RangeIterator(int start, int count)
+            {
+                _start = start;
+                _end = start + count;
+            }
+
+            public override Iterator<int> Clone() => new RangeIterator(_start, _end - _start);
+
+            public override bool MoveNext()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _next = _start;
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (_next < _end)
+                        {
+                            _current = _next++;
+                            return true;
+                        }
+                        break;
+                }
+
+                return false;
+            }
+        }
+
+        private sealed class SelectIterator<T, R> : Iterator<R>
+        {
+            private readonly IEnumerable<T> _source;
+            private readonly Func<T, R> _selector;
+            private IEnumerator<T> _enumerator;
+
+            public SelectIterator(IEnumerable<T> source, Func<T, R> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override Iterator<R> Clone() => new SelectIterator<T, R>(_source, _selector);
+
+            public override bool MoveNext()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (_enumerator.MoveNext())
+                        {
+                            _current = _selector(_enumerator.Current);
+                            return true;
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+
+        private sealed class WhereIterator<T> : Iterator<T>
+        {
+            private readonly IEnumerable<T> _source;
+            private readonly Func<T, bool> _predicate;
+            private IEnumerator<T> _enumerator;
+
+            public WhereIterator(IEnumerable<T> source, Func<T, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override Iterator<T> Clone() => new WhereIterator<T>(_source, _predicate);
+
+            public override bool MoveNext()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        while (_enumerator.MoveNext())
+                        {
+                            var item = _enumerator.Current;
+
+                            if (_predicate(item))
+                            {
+                                _current = item;
+                                return true;
+                            }
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+    }
+
+    public static class FastEnumerable
+    {
+        public static R Aggregate<T, R>(this IFastEnumerable<T> source, R seed, Func<R, T, R> aggregate)
+        {
+            var res = seed;
+
+            using (var e = source.GetEnumerator())
+            {
+                while (true)
+                {
+                    var item = e.TryGetNext(out var success);
+
+                    if (!success)
+                    {
+                        break;
+                    }
+
+                    res = aggregate(res, item);
+                }
+            }
+
+            return res;
+        }
+
+        public static IFastEnumerable<T> Empty<T>() => EmptyIterator<T>.Instance;
+
+        public static void ForEach<T>(this IFastEnumerable<T> source, Action<T> next)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (true)
+                {
+                    var item = e.TryGetNext(out var success);
+
+                    if (!success)
+                    {
+                        break;
+                    }
+
+                    next(item);
+                }
+            }
+        }
+
+        public static IFastEnumerable<int> Range(int start, int count) => new RangeIterator(start, count);
+
+        public static IFastEnumerable<R> Select<T, R>(this IFastEnumerable<T> source, Func<T, R> selector) => new SelectFastIterator<T, R>(source, selector);
+
+        public static IFastEnumerable<T> ToFastEnumerable<T>(this IEnumerable<T> source) => new EnumerableToFastEnumerable<T>(source);
+
+        public static IEnumerable<T> ToEnumerable<T>(this IFastEnumerable<T> source) => new FastEnumerableToEnumerable<T>(source);
+
+        public static IFastEnumerable<T> Where<T>(this IFastEnumerable<T> source, Func<T, bool> predicate) => new WhereFastIterator<T>(source, predicate);
+
+        private sealed class EmptyIterator<T> : IFastEnumerable<T>, IFastEnumerator<T>
+        {
+            public static readonly EmptyIterator<T> Instance = new EmptyIterator<T>();
+
+            public void Dispose() { }
+
+            public IFastEnumerator<T> GetEnumerator() => this;
+
+            public T TryGetNext(out bool success)
+            {
+                success = false;
+                return default(T);
+            }
+        }
+
+        private sealed class EnumerableToFastEnumerable<T> : FastIterator<T>
+        {
+            private readonly IEnumerable<T> _source;
+            private IEnumerator<T> _enumerator;
+
+            public EnumerableToFastEnumerable(IEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public override FastIterator<T> Clone() => new EnumerableToFastEnumerable<T>(_source);
+
+            public override T TryGetNext(out bool success)
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        success = _enumerator.MoveNext();
+                        if (success)
+                        {
+                            return _enumerator.Current;
+                        }
+                        break;
+                }
+
+                success = false;
+                return default(T);
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+
+        private sealed class FastEnumerableToEnumerable<T> : Iterator<T>
+        {
+            private readonly IFastEnumerable<T> _source;
+            private IFastEnumerator<T> _enumerator;
+
+            public FastEnumerableToEnumerable(IFastEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public override Iterator<T> Clone() => new FastEnumerableToEnumerable<T>(_source);
+
+            public override bool MoveNext()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        _current = _enumerator.TryGetNext(out var success);
+                        return success;
+                }
+
+                return false;
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+
+        private sealed class RangeIterator : FastIterator<int>
+        {
+            private readonly int _start;
+            private readonly int _end;
+            private int _next;
+
+            public RangeIterator(int start, int count)
+            {
+                _start = start;
+                _end = start + count;
+            }
+
+            public override FastIterator<int> Clone() => new RangeIterator(_start, _end - _start);
+
+            public override int TryGetNext(out bool success)
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _next = _start;
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (_next < _end)
+                        {
+                            success = true;
+                            return _next++;
+                        }
+                        break;
+                }
+
+                success = false;
+                return default(int);
+            }
+        }
+
+        private sealed class SelectFastIterator<T, R> : FastIterator<R>
+        {
+            private readonly IFastEnumerable<T> _source;
+            private readonly Func<T, R> _selector;
+            private IFastEnumerator<T> _enumerator;
+
+            public SelectFastIterator(IFastEnumerable<T> source, Func<T, R> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override FastIterator<R> Clone() => new SelectFastIterator<T, R>(_source, _selector);
+
+            public override R TryGetNext(out bool success)
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        var item = _enumerator.TryGetNext(out success);
+                        if (success)
+                        {
+                            return _selector(item);
+                        }
+                        break;
+                }
+
+                success = false;
+                return default(R);
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+
+        private sealed class WhereFastIterator<T> : FastIterator<T>
+        {
+            private readonly IFastEnumerable<T> _source;
+            private readonly Func<T, bool> _predicate;
+            private IFastEnumerator<T> _enumerator;
+
+            public WhereFastIterator(IFastEnumerable<T> source, Func<T, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override FastIterator<T> Clone() => new WhereFastIterator<T>(_source, _predicate);
+
+            public override T TryGetNext(out bool success)
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        while (true)
+                        {
+                            var item = _enumerator.TryGetNext(out success);
+                            if (!success)
+                            {
+                                break;
+                            }
+
+                            if (_predicate(item))
+                            {
+                                return item;
+                            }
+                        }
+                        break;
+                }
+
+                success = false;
+                return default(T);
+            }
+
+            public override void Dispose() => _enumerator?.Dispose();
+        }
+    }
+
+    public static class AsyncEnumerable
+    {
+        private static readonly Task<bool> True = Task.FromResult(true);
+        private static readonly Task<bool> False = Task.FromResult(false);
+
+        public static async Task<R> Aggregate<T, R>(this IAsyncEnumerable<T> source, R seed, Func<R, T, R> aggregate)
+        {
+            var res = seed;
+
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    res = aggregate(res, e.Current);
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return res;
+        }
+
+        public static async Task<R> Aggregate<T, R>(this IAsyncEnumerable<T> source, R seed, Func<R, T, Task<R>> aggregate)
+        {
+            var res = seed;
+
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (true)
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        res = await aggregate(res, e.Current).ConfigureAwait(false);
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return res;
+        }
+
+        public static IAsyncEnumerable<T> Empty<T>() => EmptyIterator<T>.Instance;
+
+        public static async Task ForEachAsync<T>(this IAsyncEnumerable<T> source, Func<T, Task> next)
+        {
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var item = e.Current;
+                    await next(item).ConfigureAwait(false);
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        public static IAsyncEnumerable<int> Range(int start, int count) => new RangeIterator(start, count);
+
+        public static IAsyncEnumerable<R> Select<T, R>(this IAsyncEnumerable<T> source, Func<T, R> selector) => new SelectIterator<T, R>(source, selector);
+
+        public static IAsyncEnumerable<R> Select<T, R>(this IAsyncEnumerable<T> source, Func<T, Task<R>> selector) => new SelectIteratorWithTask<T, R>(source, selector);
+
+        public static IAsyncEnumerable<T> Where<T>(this IAsyncEnumerable<T> source, Func<T, bool> predicate) => new WhereIterator<T>(source, predicate);
+
+        public static IAsyncEnumerable<T> Where<T>(this IAsyncEnumerable<T> source, Func<T, Task<bool>> predicate) => new WhereIteratorWithTask<T>(source, predicate);
+
+        private sealed class EmptyIterator<T> : IAsyncEnumerable<T>, IAsyncEnumerator<T>
+        {
+            public static readonly EmptyIterator<T> Instance = new EmptyIterator<T>();
+
+            public T Current => default(T);
+
+            public Task DisposeAsync() => Task.CompletedTask;
+
+            public IAsyncEnumerator<T> GetAsyncEnumerator() => this;
+
+            public Task<bool> MoveNextAsync() => False;
+        }
+
+        private sealed class RangeIterator : AsyncIterator<int>
+        {
+            private readonly int _start;
+            private readonly int _end;
+            private int _next;
+
+            public RangeIterator(int start, int count)
+            {
+                _start = start;
+                _end = start + count;
+            }
+
+            public override AsyncIterator<int> Clone() => new RangeIterator(_start, _end - _start);
+
+            public override Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _next = _start;
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (_next < _end)
+                        {
+                            _current = _next++;
+                            return True;
+                        }
+                        break;
+                }
+
+                return False;
+            }
+        }
+
+        private sealed class SelectIterator<T, R> : AsyncIterator<R>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+            private readonly Func<T, R> _selector;
+            private IAsyncEnumerator<T> _enumerator;
+
+            public SelectIterator(IAsyncEnumerable<T> source, Func<T, R> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override AsyncIterator<R> Clone() => new SelectIterator<T, R>(_source, _selector);
+
+            public override async Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (await _enumerator.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            _current = _selector(_enumerator.Current);
+                            return true;
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+        }
+
+        private sealed class SelectIteratorWithTask<T, R> : AsyncIterator<R>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+            private readonly Func<T, Task<R>> _selector;
+            private IAsyncEnumerator<T> _enumerator;
+
+            public SelectIteratorWithTask(IAsyncEnumerable<T> source, Func<T, Task<R>> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override AsyncIterator<R> Clone() => new SelectIteratorWithTask<T, R>(_source, _selector);
+
+            public override async Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (await _enumerator.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            _current = await _selector(_enumerator.Current).ConfigureAwait(false);
+                            return true;
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+        }
+
+        private sealed class WhereIterator<T> : AsyncIterator<T>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+            private readonly Func<T, bool> _predicate;
+            private IAsyncEnumerator<T> _enumerator;
+
+            public WhereIterator(IAsyncEnumerable<T> source, Func<T, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override AsyncIterator<T> Clone() => new WhereIterator<T>(_source, _predicate);
+
+            public override async Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            var item = _enumerator.Current;
+
+                            if (_predicate(item))
+                            {
+                                _current = item;
+                                return true;
+                            }
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+        }
+
+        private sealed class WhereIteratorWithTask<T> : AsyncIterator<T>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+            private readonly Func<T, Task<bool>> _predicate;
+            private IAsyncEnumerator<T> _enumerator;
+
+            public WhereIteratorWithTask(IAsyncEnumerable<T> source, Func<T, Task<bool>> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override AsyncIterator<T> Clone() => new WhereIteratorWithTask<T>(_source, _predicate);
+
+            public override async Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            var item = _enumerator.Current;
+
+                            if (await _predicate(item).ConfigureAwait(false))
+                            {
+                                _current = item;
+                                return true;
+                            }
+                        }
+                        break;
+                }
+
+                return false;
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+        }
+    }
+
+    public static class AsyncFastEnumerable
+    {
+        private static readonly Task<bool> True = Task.FromResult(true);
+        private static readonly Task<bool> False = Task.FromResult(false);
+
+        public static async Task<R> Aggregate<T, R>(this IAsyncFastEnumerable<T> source, R seed, Func<R, T, R> aggregate)
+        {
+            var res = seed;
+
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (await e.WaitForNextAsync().ConfigureAwait(false))
+                {
+                    while (true)
+                    {
+                        var item = e.TryGetNext(out var success);
+
+                        if (!success)
+                        {
+                            break;
+                        }
+
+                        res = aggregate(res, item);
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return res;
+        }
+
+        public static async Task<R> Aggregate<T, R>(this IAsyncFastEnumerable<T> source, R seed, Func<R, T, Task<R>> aggregate)
+        {
+            var res = seed;
+
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (await e.WaitForNextAsync().ConfigureAwait(false))
+                {
+                    while (true)
+                    {
+                        var item = e.TryGetNext(out var success);
+
+                        if (!success)
+                        {
+                            break;
+                        }
+
+                        res = await aggregate(res, item).ConfigureAwait(false);
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return res;
+        }
+
+        public static IAsyncFastEnumerable<T> Empty<T>() => EmptyIterator<T>.Instance;
+
+        public static async Task ForEachAsync<T>(this IAsyncFastEnumerable<T> source, Func<T, Task> next)
+        {
+            var e = source.GetAsyncEnumerator();
+
+            try
+            {
+                while (await e.WaitForNextAsync().ConfigureAwait(false))
+                {
+                    while (true)
+                    {
+                        var item = e.TryGetNext(out var success);
+
+                        if (!success)
+                        {
+                            break;
+                        }
+
+                        await next(item).ConfigureAwait(false);
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        public static IAsyncFastEnumerable<int> Range(int start, int count) => new RangeIterator(start, count);
+
+        public static IAsyncFastEnumerable<R> Select<T, R>(this IAsyncFastEnumerable<T> source, Func<T, R> selector) => new SelectFastIterator<T, R>(source, selector);
+
+        public static IAsyncFastEnumerable<R> Select<T, R>(this IAsyncFastEnumerable<T> source, Func<T, Task<R>> selector) => new SelectFastIteratorWithTask<T, R>(source, selector);
+
+        public static IAsyncFastEnumerable<T> ToAsyncFastEnumerable<T>(this IAsyncEnumerable<T> source) => new AsyncEnumerableToAsyncFastEnumerable<T>(source);
+
+        public static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncFastEnumerable<T> source) => new AsyncFastEnumerableToAsyncEnumerable<T>(source);
+
+        public static IAsyncFastEnumerable<T> Where<T>(this IAsyncFastEnumerable<T> source, Func<T, bool> predicate) => new WhereFastIterator<T>(source, predicate);
+
+        public static IAsyncFastEnumerable<T> Where<T>(this IAsyncFastEnumerable<T> source, Func<T, Task<bool>> predicate) => new WhereFastIteratorWithTask<T>(source, predicate);
+
+        private sealed class EmptyIterator<T> : IAsyncFastEnumerable<T>, IAsyncFastEnumerator<T>
+        {
+            public static readonly EmptyIterator<T> Instance = new EmptyIterator<T>();
+
+            public Task DisposeAsync() => Task.CompletedTask;
+
+            public IAsyncFastEnumerator<T> GetAsyncEnumerator() => this;
+
+            public T TryGetNext(out bool success)
+            {
+                success = false;
+                return default(T);
+            }
+
+            public Task<bool> WaitForNextAsync() => False;
+        }
+
+        private sealed class AsyncEnumerableToAsyncFastEnumerable<T> : AsyncFastIterator<T>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+            private IAsyncEnumerator<T> _enumerator;
+            private bool _hasNext;
+
+            public AsyncEnumerableToAsyncFastEnumerable(IAsyncEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public override AsyncFastIterator<T> Clone() => new AsyncEnumerableToAsyncFastEnumerable<T>(_source);
+
+            public override T TryGetNext(out bool success)
+            {
+                success = _hasNext;
+                _hasNext = false;
+
+                return success ? _enumerator.Current : default(T);
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+
+            public override async Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        _hasNext = await _enumerator.MoveNextAsync().ConfigureAwait(false);
+                        return _hasNext;
+                }
+
+                return false;
+            }
+        }
+
+        private sealed class AsyncFastEnumerableToAsyncEnumerable<T> : AsyncIterator<T>
+        {
+            private readonly IAsyncFastEnumerable<T> _source;
+            private IAsyncFastEnumerator<T> _enumerator;
+
+            public AsyncFastEnumerableToAsyncEnumerable(IAsyncFastEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public override AsyncIterator<T> Clone() => new AsyncFastEnumerableToAsyncEnumerable<T>(_source);
+
+            public override async Task<bool> MoveNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        do
+                        {
+                            while (true)
+                            {
+                                var item = _enumerator.TryGetNext(out var success);
+
+                                if (!success)
+                                {
+                                    break;
+                                }
+                                else
+                                {
+                                    _current = item;
+                                    return true;
+                                }
+                            }
+                        } while (await _enumerator.WaitForNextAsync().ConfigureAwait(false));
+
+                        break;
+                }
+
+                return false;
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+        }
+
+        private sealed class RangeIterator : AsyncFastIterator<int>
+        {
+            private readonly int _start;
+            private readonly int _end;
+            private int _next;
+
+            public RangeIterator(int start, int count)
+            {
+                _start = start;
+                _end = start + count;
+            }
+
+            public override AsyncFastIterator<int> Clone() => new RangeIterator(_start, _end - _start);
+
+            public override int TryGetNext(out bool success)
+            {
+                if (_state == 2 && _next < _end)
+                {
+                    success = true;
+                    return _next++;
+                }
+
+                success = false;
+                return default(int);
+            }
+
+            public override Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _next = _start;
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        if (_next < _end)
+                        {
+                            return True;
+                        }
+                        break;
+                }
+
+                return False;
+            }
+        }
+
+        private sealed class SelectFastIterator<T, R> : AsyncFastIterator<R>
+        {
+            private readonly IAsyncFastEnumerable<T> _source;
+            private readonly Func<T, R> _selector;
+            private IAsyncFastEnumerator<T> _enumerator;
+
+            public SelectFastIterator(IAsyncFastEnumerable<T> source, Func<T, R> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override AsyncFastIterator<R> Clone() => new SelectFastIterator<T, R>(_source, _selector);
+
+            public override R TryGetNext(out bool success)
+            {
+                if (_enumerator != null)
+                {
+                    var item = _enumerator.TryGetNext(out success);
+                    if (success)
+                    {
+                        return _selector(item);
+                    }
+                }
+
+                success = false;
+                return default(R);
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+
+            public override Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        return _enumerator.WaitForNextAsync();
+                }
+
+                return False;
+            }
+        }
+
+        private sealed class SelectFastIteratorWithTask<T, R> : AsyncFastIterator<R>
+        {
+            private readonly IAsyncFastEnumerable<T> _source;
+            private readonly Func<T, Task<R>> _selector;
+            private IAsyncFastEnumerator<T> _enumerator;
+            private bool _hasNext;
+            private R _next;
+
+            public SelectFastIteratorWithTask(IAsyncFastEnumerable<T> source, Func<T, Task<R>> selector)
+            {
+                _source = source;
+                _selector = selector;
+            }
+
+            public override AsyncFastIterator<R> Clone() => new SelectFastIteratorWithTask<T, R>(_source, _selector);
+
+            public override R TryGetNext(out bool success)
+            {
+                success = _hasNext;
+                _hasNext = false;
+
+                return success ? _next : default(R);
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+
+            public override async Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        do
+                        {
+                            while (true)
+                            {
+                                var item = _enumerator.TryGetNext(out var success);
+
+                                if (!success)
+                                {
+                                    break;
+                                }
+                                else
+                                {
+                                    _hasNext = true;
+                                    _next = await _selector(item).ConfigureAwait(false);
+                                    return true;
+                                }
+                            }
+                        }
+                        while (await _enumerator.WaitForNextAsync().ConfigureAwait(false));
+
+                        break;
+                }
+
+                _hasNext = false;
+                _next = default(R);
+
+                return false;
+            }
+        }
+
+        private sealed class WhereFastIterator<T> : AsyncFastIterator<T>
+        {
+            private readonly IAsyncFastEnumerable<T> _source;
+            private readonly Func<T, bool> _predicate;
+            private IAsyncFastEnumerator<T> _enumerator;
+
+            public WhereFastIterator(IAsyncFastEnumerable<T> source, Func<T, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override AsyncFastIterator<T> Clone() => new WhereFastIterator<T>(_source, _predicate);
+
+            public override T TryGetNext(out bool success)
+            {
+                if (_enumerator != null)
+                {
+                    while (true)
+                    {
+                        var item = _enumerator.TryGetNext(out success);
+                        if (!success)
+                        {
+                            break;
+                        }
+
+                        if (_predicate(item))
+                        {
+                            return item;
+                        }
+                    }
+                }
+
+                success = false;
+                return default(T);
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+
+            public override Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        return _enumerator.WaitForNextAsync();
+                }
+
+                return False;
+            }
+        }
+
+        private sealed class WhereFastIteratorWithTask<T> : AsyncFastIterator<T>
+        {
+            private readonly IAsyncFastEnumerable<T> _source;
+            private readonly Func<T, Task<bool>> _predicate;
+            private IAsyncFastEnumerator<T> _enumerator;
+            private bool _hasNext;
+            private T _next;
+
+            public WhereFastIteratorWithTask(IAsyncFastEnumerable<T> source, Func<T, Task<bool>> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            public override AsyncFastIterator<T> Clone() => new WhereFastIteratorWithTask<T>(_source, _predicate);
+
+            public override T TryGetNext(out bool success)
+            {
+                success = _hasNext;
+                _hasNext = false;
+
+                return success ? _next : default(T);
+            }
+
+            public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask;
+
+            public override async Task<bool> WaitForNextAsync()
+            {
+                switch (_state)
+                {
+                    case 1:
+                        _enumerator = _source.GetAsyncEnumerator();
+                        _state = 2;
+                        goto case 2;
+
+                    case 2:
+                        do
+                        {
+                            while (true)
+                            {
+                                var item = _enumerator.TryGetNext(out var success);
+
+                                if (!success)
+                                {
+                                    break;
+                                }
+                                else
+                                {
+                                    if (await _predicate(item).ConfigureAwait(false))
+                                    {
+                                        _hasNext = true;
+                                        _next = item;
+                                        return true;
+                                    }
+                                }
+                            }
+                        }
+                        while (await _enumerator.WaitForNextAsync().ConfigureAwait(false));
+
+                        break;
+                }
+
+                _hasNext = false;
+                _next = default(T);
+
+                return false;
+            }
+        }
+    }
+}

+ 19 - 0
Ix.NET/Source/Ix.NET.sln

@@ -51,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async.Queryable
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Async.Providers.Tests", "System.Interactive.Async.Providers.Tests\System.Interactive.Async.Providers.Tests.csproj", "{974056C0-91BD-4EB6-8431-E30A614FD1D4}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FasterLinq", "FasterLinq\FasterLinq.csproj", "{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -295,6 +297,22 @@ Global
 		{974056C0-91BD-4EB6-8431-E30A614FD1D4}.Release|x64.Build.0 = Release|Any CPU
 		{974056C0-91BD-4EB6-8431-E30A614FD1D4}.Release|x86.ActiveCfg = Release|Any CPU
 		{974056C0-91BD-4EB6-8431-E30A614FD1D4}.Release|x86.Build.0 = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|ARM.Build.0 = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|x64.Build.0 = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Debug|x86.Build.0 = Debug|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|ARM.ActiveCfg = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|ARM.Build.0 = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|x64.ActiveCfg = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|x64.Build.0 = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|x86.ActiveCfg = Release|Any CPU
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -314,6 +332,7 @@ Global
 		{2E23D7AD-0B21-4725-87C4-BD43271260A1} = {87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}
 		{134E9066-6217-4AF0-B408-47D92AB595BD} = {87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}
 		{974056C0-91BD-4EB6-8431-E30A614FD1D4} = {87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}
+		{1C966C34-0AA1-44D8-9E7D-C7866958F2D6} = {61683064-A120-44A7-A174-E19154F6D84F}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {AF70B0C6-C9D9-43B1-9BE4-08720EC1B7B7}