From 77b9fd82a7ef68f894a25ef79787ec3616b48e99 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 22 Jun 2018 17:45:23 +0200 Subject: [PATCH 1/2] Add Benchmark for Switch. --- .../Benchmarks.System.Reactive/Program.cs | 3 ++- .../SwitchBenchmark.cs | 25 +++++++++++++++++++ .../ZipBenchmark.cs | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/SwitchBenchmark.cs diff --git a/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/Program.cs b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/Program.cs index 3776f8cad8..ad89ca78d4 100644 --- a/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/Program.cs +++ b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/Program.cs @@ -13,7 +13,8 @@ static void Main() { var switcher = new BenchmarkSwitcher(new[] { typeof(ZipBenchmark), - typeof(CombineLatestBenchmark) + typeof(CombineLatestBenchmark), + typeof(SwitchBenchmark) }); switcher.Run(); diff --git a/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/SwitchBenchmark.cs b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/SwitchBenchmark.cs new file mode 100644 index 0000000000..17b94c1f4d --- /dev/null +++ b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/SwitchBenchmark.cs @@ -0,0 +1,25 @@ +// 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.Reactive.Linq; +using BenchmarkDotNet.Attributes; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; + +namespace Benchmarks.System.Reactive +{ + [MemoryDiagnoser] + public class SwitchBenchmark + { + [Benchmark] + public async Task Switch_10000_Sources() + { + await Observable + .Range(1, 10000) + .Select(x => Observable.Return(x)) + .Switch() + .ToTask(); + } + } +} diff --git a/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/ZipBenchmark.cs b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/ZipBenchmark.cs index 108264c247..53720dd4b5 100644 --- a/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/ZipBenchmark.cs +++ b/Rx.NET/Source/benchmarks/Benchmarks.System.Reactive/ZipBenchmark.cs @@ -77,7 +77,7 @@ public void Zip_AllCompleted7() { _zipTest.Zip_AllCompleted7(); } - + [Benchmark] public void Zip_AllCompleted8() { From 3658aae7da34aef22504496888fe91cdfa92b635 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Tue, 19 Jun 2018 16:56:06 +0200 Subject: [PATCH 2/2] Save an allocation during inner observer creation in Switch. --- .../System.Reactive/Linq/Observable/Switch.cs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs index 139f4ae388..45642046dc 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs @@ -50,9 +50,10 @@ public override void OnNext(IObservable value) _hasLatest = true; } - var d = new SingleAssignmentDisposable(); - Disposable.TrySetSerial(ref _innerSerialDisposable, d); - d.Disposable = value.SubscribeSafe(new InnerObserver(this, id, d)); + var innerObserver = new InnerObserver(this, id); + + Disposable.TrySetSerial(ref _innerSerialDisposable, innerObserver); + innerObserver.SetResource(value.SubscribeSafe(innerObserver)); } public override void OnError(Exception error) @@ -75,20 +76,18 @@ public override void OnCompleted() } } - private sealed class InnerObserver : IObserver + private sealed class InnerObserver : SafeObserver { private readonly _ _parent; private readonly ulong _id; - private readonly IDisposable _self; - public InnerObserver(_ parent, ulong id, IDisposable self) + public InnerObserver(_ parent, ulong id) { _parent = parent; _id = id; - _self = self; } - public void OnNext(TSource value) + public override void OnNext(TSource value) { lock (_parent._gate) { @@ -99,11 +98,11 @@ public void OnNext(TSource value) } } - public void OnError(Exception error) + public override void OnError(Exception error) { lock (_parent._gate) { - _self.Dispose(); + Dispose(); if (_parent._latest == _id) { @@ -112,11 +111,11 @@ public void OnError(Exception error) } } - public void OnCompleted() + public override void OnCompleted() { lock (_parent._gate) { - _self.Dispose(); + Dispose(); if (_parent._latest == _id) {