Skip to content

Commit

Permalink
Added Benchmark Harness (#1729)
Browse files Browse the repository at this point in the history
- Added NavigationStack Benchmarks
- Added AutoPersist Benchmarks
- Added ReactiveList Operations Benchmarks
- Added RoutableViewModelMixin Benchmarks
  • Loading branch information
RLittlesII committed Aug 24, 2018
1 parent 18d3fd1 commit a15c758
Show file tree
Hide file tree
Showing 11 changed files with 444 additions and 0 deletions.
39 changes: 39 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks.sln
@@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2000
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI.Benchmarks", "ReactiveUI.Benchmarks\ReactiveUI.Benchmarks.csproj", "{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{0DB2C65F-BE8F-4021-8860-D2D6EB9DD80A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CB287F1A-1E15-40D7-85F5-F2A97A944B57}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI", "..\src\ReactiveUI\ReactiveUI.csproj", "{1BB9FAA2-4E90-4E93-8B77-434DF10166ED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A}.Release|Any CPU.Build.0 = Release|Any CPU
{1BB9FAA2-4E90-4E93-8B77-434DF10166ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BB9FAA2-4E90-4E93-8B77-434DF10166ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BB9FAA2-4E90-4E93-8B77-434DF10166ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BB9FAA2-4E90-4E93-8B77-434DF10166ED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EC6DD0F1-4D99-4BE8-B3F1-1DD71D86C24A} = {0DB2C65F-BE8F-4021-8860-D2D6EB9DD80A}
{1BB9FAA2-4E90-4E93-8B77-434DF10166ED} = {CB287F1A-1E15-40D7-85F5-F2A97A944B57}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A602807A-CF55-4092-A5CD-646572A09B88}
EndGlobalSection
EndGlobal
31 changes: 31 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/AutoPersistBenchmark.cs
@@ -0,0 +1,31 @@
using System;
using System.Reactive;
using System.Reactive.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;

namespace ReactiveUI.Benchmarks
{
[CoreJob]
[MarkdownExporterAttribute.GitHub]
public class AutoPersistBenchmark
{
private ReactiveList<string> _collection;

[GlobalSetup]
public void Setup()
{
_collection = new ReactiveList<string>(new[]
{
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events"
});
}

[Benchmark]
public void AutoPersistCollection() => _collection.AutoPersist(x => Observable.Return(Unit.Default), TimeSpan.FromMilliseconds(200));
}
}
47 changes: 47 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/CreateReactiveListBenchmark.cs
@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains.CsProj;
using DynamicData;

namespace ReactiveUI.Benchmarks
{
[CoreJob]
[MarkdownExporterAttribute.GitHub]
public class CreateReactiveListBenchmark
{
[Benchmark(Baseline = true)]
public object CreateList() => new List<string>();

[Benchmark]
public object CreateObservableCollection() => new ObservableCollection<string>();

[Benchmark]
public object CreateReactiveList() => new ReactiveList<string>();

[Benchmark]
public object CreateReactiveListFromList() => new ReactiveList<string>(new string[]
{
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events",
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events"
});

[Benchmark]
public object CreateReadOnlyObservableList() =>
new ReadOnlyObservableCollection<string>(new ObservableCollection<string>(Enumerable.Empty<string>()));

[Benchmark]
public object CreateSourceList() => new SourceList<string>().Connect().AsObservableList();
}
}
45 changes: 45 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/Harness.cs
@@ -0,0 +1,45 @@
using System;
using BenchmarkDotNet.Running;
using Xunit;

namespace ReactiveUI.Benchmarks
{
public class Harness
{
[Fact]
public void Auto_Persist_Benchmark()
{
BenchmarkRunner.Run<AutoPersistBenchmark>();
}

[Fact]
public void Create_Reactive_List_Benchmark()
{
BenchmarkRunner.Run<CreateReactiveListBenchmark>();
}

[Fact]
public void Reactive_List_Operation_Benchmark()
{
BenchmarkRunner.Run<ReactiveListOperationBenchmark>();
}

[Fact]
public void Navigation_Reactive_List_Benchmark()
{
BenchmarkRunner.Run<NavigationStackBenchmark>();
}

[Fact]
public void Routable_View_Model_Mixin_Benchmark()
{
BenchmarkRunner.Run<RoutableViewModelMixinsBenchmarks>();
}

[Fact]
public void INPC_Observable_For_Property_Benchmarks()
{
BenchmarkRunner.Run<INPCObservableForPropertyBenchmarks>();
}
}
}
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;

namespace ReactiveUI.Benchmarks
{
[ClrJob]
[CoreJob]
[MonoJob]
[RPlotExporter]
[RankColumn]
[MarkdownExporterAttribute.GitHub]
public class INPCObservableForPropertyBenchmarks
{
private Expression exp;
private readonly Expression<Func<TestClassChanged, string>> expr = x => x.Property1;
private readonly INPCObservableForProperty instance = new INPCObservableForProperty();
private string propertyName;


[GlobalSetup]
public void Setup()
{
exp = Reflection.Rewrite(expr.Body);
propertyName = exp.GetMemberInfo().Name;
}

[Benchmark]
public void PropertyBinding()
{
var testClass = new TestClassChanged();

var changes = new List<IObservedChange<object, object>>();
instance.GetNotificationForProperty(testClass, exp, propertyName, false).Subscribe(c => changes.Add(c));
}

private class TestClassChanged : INotifyPropertyChanged
{
private string property;

private string property2;

public string Property1
{
get => property;
set
{
property = value;
OnPropertyChanged();
}
}

public string Property2
{
get => property2;
set
{
property2 = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
7 changes: 7 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/Mocks/MockHostScreen.cs
@@ -0,0 +1,7 @@
namespace ReactiveUI.Benchmarks
{
public class MockHostScreen : IScreen
{
public RoutingState Router { get; } = new RoutingState();
}
}
10 changes: 10 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/Mocks/MockViewModel.cs
@@ -0,0 +1,10 @@
namespace ReactiveUI.Benchmarks
{
public class MockViewModel : ReactiveObject, IRoutableViewModel
{
public IScreen HostScreen { get; }
public string UrlPathSegment { get; }

public MockViewModel() => HostScreen = new MockHostScreen();
}
}
53 changes: 53 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/NavigationStackBenchmark.cs
@@ -0,0 +1,53 @@
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;

namespace ReactiveUI.Benchmarks
{
[CoreJob]
[MarkdownExporterAttribute.GitHub]
public class NavigationStackBenchmark
{
private Func<MockViewModel> _mockViewModel;
private RoutingState _router;

[GlobalCleanup]
public void Cleanup()
{
_router = null;
_mockViewModel = null;
}

[Benchmark]
public object Navigate() => _router.Navigate.Execute(_mockViewModel()).Subscribe();

[Benchmark]
public object NavigateAndReset() => _router.NavigateAndReset.Execute(_mockViewModel()).Subscribe();

[Benchmark]
public object NavigateBack()
{
_router.NavigateAndReset.Execute(_mockViewModel()).Subscribe();
return _router.NavigateBack.Execute().Subscribe();
}

[Benchmark]
public object NavigationStack()
{
_router.NavigateAndReset.Execute(_mockViewModel()).Subscribe();
return _router.NavigationStack.ToList();
}

[Benchmark]
public object RoutingState() => new RoutingState();

[GlobalSetup]
public void Setup()
{
_router = new RoutingState();
_mockViewModel = () => new MockViewModel();
}
}
}
61 changes: 61 additions & 0 deletions benchmarks/ReactiveUI.Benchmarks/ReactiveListOperationBenchmark.cs
@@ -0,0 +1,61 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using DynamicData;

namespace ReactiveUI.Benchmarks
{
[CoreJob]
[MarkdownExporterAttribute.GitHub]
public class ReactiveListOperationBenchmark
{
private ReactiveList<string> _reactiveList;

[GlobalSetup]
public void Setup()
{
_reactiveList = new ReactiveList<string>();
}

[GlobalCleanup]
public void Teardown()
{
_reactiveList = null;
}

[Benchmark]
public void Add() => _reactiveList.Add("ReactiveUI.Fody");

[Benchmark]
public void AddRange() => _reactiveList.AddRange(new[]
{
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events",
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events"
});

[Benchmark]
public void AddOrInsertRange() => _reactiveList.AddOrInsertRange(new[]
{
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events",
"ReactiveUI",
"ReactiveUI.XamForms",
"ReactiveUI.WPF",
"ReactiveUI.Events"
}, -1);

[Benchmark]
public void Insert() => _reactiveList.Insert(1, "ReactiveUI.Benchmarks");

[Benchmark]
public void RemoveItem() => _reactiveList.Remove("ReactiveUI");
}
}

0 comments on commit a15c758

Please sign in to comment.