123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- // 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.Reactive.Concurrency;
- using System.Reactive.Disposables;
- using System.Reactive.Linq;
- using System.Reactive.Subjects;
- using System.Threading;
- using BenchmarkDotNet.Attributes;
- namespace Benchmarks.System.Reactive
- {
- [MemoryDiagnoser]
- public class ComparisonBenchmark
- {
- [Params(1, 10, 100, 1000, 10000, 100000, 1000000)]
- public int N;
- private int _store;
- [Benchmark]
- public void ForLoopBaseLine()
- {
- var n = N;
- for (var i = 0; i < N; i++)
- {
- Volatile.Write(ref _store, i);
- }
- }
- [Benchmark]
- public void EnumerableBaseLine()
- {
- foreach (var v in Enumerable.Range(1, N))
- {
- Volatile.Write(ref _store, v);
- }
- }
- [Benchmark]
- public void Return()
- {
- Observable.Return(1).Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Range()
- {
- Observable.Range(1, N).Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Select()
- {
- Observable.Range(1, N)
- .Select(v => v + 1)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void SelectSelect()
- {
- Observable.Range(1, N)
- .Select(v => v + 1)
- .Select(v => v + 1)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Where()
- {
- Observable.Range(1, 2 * N)
- .Where(v => (v & 1) != 0)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void WhereWhere()
- {
- Observable.Range(1, 4 * N)
- .Where(v => (v & 1) != 0)
- .Where(v => (v & 2) != 0)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Take()
- {
- Observable.Range(1, 2 * N)
- .Take(N)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Skip()
- {
- Observable.Range(1, 2 * N)
- .Skip(N)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void TakeUntil()
- {
- Observable.Range(1, N)
- .TakeUntil(Observable.Never<int>())
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void ToObservable()
- {
- Enumerable.Range(1, N)
- .ToObservable()
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Concat()
- {
- var M = N - N / 2;
- Observable.Concat(
- Observable.Range(1, N),
- Observable.Range(1, M)
- )
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void ConcatCrossMap()
- {
- var M = 1000 * 1000 / N;
- Observable.Concat(Observable.Range(1, N).Select(v => Observable.Range(v, M)))
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void SelectManyCrossMap()
- {
- var M = 1000 * 1000 / N;
- Observable.Range(1, N).SelectMany(v => Observable.Range(v, M))
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void MergeCrossMap()
- {
- var M = 1000 * 1000 / N;
- Observable.Merge(Observable.Range(1, N)
- .Select(v => Observable.Range(v, M))
- )
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void AsyncSubjectPush()
- {
- var subj = new AsyncSubject<int>();
- subj.Subscribe(v => Volatile.Write(ref _store, v));
- var n = N;
- for (var i = 0; i < N; i++)
- {
- subj.OnNext(i);
- }
- subj.OnCompleted();
- }
- [Benchmark]
- public void SubjectPush()
- {
- var subj = new Subject<int>();
- subj.Subscribe(v => Volatile.Write(ref _store, v));
- var n = N;
- for (var i = 0; i < N; i++)
- {
- subj.OnNext(i);
- }
- subj.OnCompleted();
- }
- [Benchmark]
- public void AmbTwo()
- {
- Observable.Never<int>().Amb(Observable.Range(1, N))
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void AmbThree()
- {
- Observable.Amb(Observable.Never<int>(), Observable.Never<int>(), Observable.Range(1, N))
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Timeout()
- {
- Observable.Range(1, N)
- .Timeout(TimeSpan.FromHours(1))
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- #pragma warning disable CS0618 // Type or member is obsolete
- [Benchmark]
- public void First()
- {
- Volatile.Write(ref _store, Observable.Range(1, N)
- .First());
- }
- [Benchmark]
- public void Last()
- {
- Volatile.Write(ref _store, Observable.Range(1, N)
- .Last());
- }
- #pragma warning restore CS0618 // Type or member is obsolete
- private IList<int> _bufferStore;
- [Benchmark]
- public void Buffer_Exact()
- {
- Observable.Range(1, 1000)
- .Buffer(1)
- .Subscribe(v => Volatile.Write(ref _bufferStore, v));
- }
- [Benchmark]
- public void Buffer_Skip()
- {
- Observable.Range(1, 1000)
- .Buffer(1, 2)
- .Subscribe(v => Volatile.Write(ref _bufferStore, v));
- }
- [Benchmark]
- public void Buffer_Overlap()
- {
- Observable.Range(1, 1000)
- .Buffer(2, 1)
- .Subscribe(v => Volatile.Write(ref _bufferStore, v));
- }
- [Benchmark]
- public void CurrentThreadSchedulerRepeated()
- {
- var n = N;
- var scheduler = CurrentThreadScheduler.Instance;
- for (var i = 0; i < n; i++)
- {
- scheduler.Schedule(i, (_, v) =>
- {
- Volatile.Write(ref _store, v);
- return Disposable.Empty;
- });
- }
- }
- [Benchmark]
- public void TakeLast()
- {
- Observable.Range(1, 2 * N).TakeLast(N)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void Repeat()
- {
- Observable.Repeat(1, N)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- [Benchmark]
- public void ToList()
- {
- Observable.Repeat(1, N).ToList()
- .Subscribe(v => Volatile.Write(ref _bufferStore, v));
- }
- [Benchmark]
- public void Generate()
- {
- Observable.Generate(0, s => s < N, s => s + 1, s => s)
- .Subscribe(v => Volatile.Write(ref _store, v));
- }
- }
- }
|