-
-
Save Sergio0694/f3e072845b01cd2e4e7e5fcc8c7a1156 to your computer and use it in GitHub Desktop.
A benchmark for different Messenger classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Configs; | |
using Calcium.Messaging; | |
using Microsoft.Toolkit.Mvvm.Messaging; | |
using MvvmLightMessenger = GalaSoft.MvvmLight.Messaging.Messenger; | |
using CalciumMessenger = Calcium.Messaging.Messenger; | |
using MicrosoftToolkitMessenger = Microsoft.Toolkit.Mvvm.Messaging.Messenger; | |
namespace IocBenchmark.Benchmarks | |
{ | |
[MemoryDiagnoser] | |
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] | |
[CategoriesColumn] | |
public class MessengerBenchmark | |
{ | |
private const string DefaultChannel = nameof(DefaultChannel); | |
private const string MultipleChannels = nameof(MultipleChannels); | |
public const int NumberOfRecipients = 200; | |
public const int NumberOfIterations = 1000; | |
public const int RandomizeSteps = 1000; | |
private readonly A a = new A(); | |
private readonly B b = new B(); | |
private readonly C c = new C(); | |
private readonly D d = new D(); | |
private Recipient[] recipients; | |
private readonly MvvmLightMessenger mvvmLightMessenger = new MvvmLightMessenger(); | |
private readonly CalciumMessenger calciumMessenger = new CalciumMessenger(); | |
private readonly MicrosoftToolkitMessenger wctMessenger = new MicrosoftToolkitMessenger(); | |
[GlobalSetup] | |
public void Setup() | |
{ | |
this.recipients = Enumerable.Range(0, NumberOfRecipients).Select(_ => new Recipient()).ToArray(); | |
foreach (var recipient in this.recipients) | |
{ | |
Register(recipient); | |
} | |
var pending = new Queue<Recipient>(); | |
var random = new Random(42); | |
for (int i = 0; i < RandomizeSteps; i++) | |
{ | |
if (random.Next(0, 2) == 1) | |
{ | |
ref Recipient recipient = ref this.recipients[random.Next(0, NumberOfRecipients)]; | |
if (recipient is null) continue; | |
Unregister(recipient); | |
pending.Enqueue(recipient); | |
recipient = null; | |
} | |
else if (pending.TryDequeue(out Recipient recipient)) | |
{ | |
foreach (ref Recipient slot in this.recipients.AsSpan()) | |
{ | |
if (slot is null) | |
{ | |
slot = recipient; | |
Register(recipient); | |
break; | |
} | |
} | |
} | |
} | |
int j = 0; | |
while (pending.TryDequeue(out Recipient recipient)) | |
{ | |
while (this.recipients[j] is null) j++; | |
this.recipients[j] = recipient; | |
Register(recipient); | |
} | |
} | |
private void Register(Recipient recipient) | |
{ | |
this.mvvmLightMessenger.Register<A>(recipient, recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<B>(recipient, recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<C>(recipient, recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<D>(recipient, recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<A>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<A>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<A>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<A>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<B>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<B>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<B>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<B>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<C>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<C>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<C>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<C>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<D>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<D>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<D>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.mvvmLightMessenger.Register<D>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.calciumMessenger.Subscribe(recipient); | |
this.wctMessenger.Register<A>(recipient, recipient.ReceiveMessage); | |
this.wctMessenger.Register<B>(recipient, recipient.ReceiveMessage); | |
this.wctMessenger.Register<C>(recipient, recipient.ReceiveMessage); | |
this.wctMessenger.Register<D>(recipient, recipient.ReceiveMessage); | |
this.wctMessenger.Register<A, string>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.wctMessenger.Register<A, string>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.wctMessenger.Register<A, string>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.wctMessenger.Register<A, string>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.wctMessenger.Register<B, string>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.wctMessenger.Register<B, string>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.wctMessenger.Register<B, string>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.wctMessenger.Register<B, string>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.wctMessenger.Register<C, string>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.wctMessenger.Register<C, string>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.wctMessenger.Register<C, string>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.wctMessenger.Register<C, string>(recipient, nameof(D), recipient.ReceiveMessage); | |
this.wctMessenger.Register<D, string>(recipient, nameof(A), recipient.ReceiveMessage); | |
this.wctMessenger.Register<D, string>(recipient, nameof(B), recipient.ReceiveMessage); | |
this.wctMessenger.Register<D, string>(recipient, nameof(C), recipient.ReceiveMessage); | |
this.wctMessenger.Register<D, string>(recipient, nameof(D), recipient.ReceiveMessage); | |
} | |
private void Unregister(Recipient recipient) | |
{ | |
this.mvvmLightMessenger.Unregister(recipient); | |
this.calciumMessenger.Unsubscribe(recipient); | |
this.wctMessenger.Unregister(recipient); | |
} | |
[Benchmark(Baseline = true)] | |
[BenchmarkCategory(DefaultChannel)] | |
public void MVVM_DefaultChannel() | |
{ | |
var a = this.a; | |
var b = this.b; | |
var c = this.c; | |
var d = this.d; | |
for (int i = NumberOfIterations; i > 0; i--) | |
{ | |
this.mvvmLightMessenger.Send(a); | |
this.mvvmLightMessenger.Send(b); | |
this.mvvmLightMessenger.Send(c); | |
this.mvvmLightMessenger.Send(d); | |
} | |
} | |
[Benchmark] | |
[BenchmarkCategory(DefaultChannel)] | |
public async Task Calcium_DefaultChannel() | |
{ | |
var a = this.a; | |
var b = this.b; | |
var c = this.c; | |
var d = this.d; | |
for (int i = NumberOfIterations; i > 0; i--) | |
{ | |
await this.calciumMessenger.PublishAsync(a); | |
await this.calciumMessenger.PublishAsync(b); | |
await this.calciumMessenger.PublishAsync(c); | |
await this.calciumMessenger.PublishAsync(d); | |
} | |
} | |
[Benchmark] | |
[BenchmarkCategory(DefaultChannel)] | |
public void WCT_DefaultChannel() | |
{ | |
var a = this.a; | |
var b = this.b; | |
var c = this.c; | |
var d = this.d; | |
for (int i = NumberOfIterations; i > 0; i--) | |
{ | |
this.wctMessenger.Send(a); | |
this.wctMessenger.Send(b); | |
this.wctMessenger.Send(c); | |
this.wctMessenger.Send(d); | |
} | |
} | |
[Benchmark(Baseline = true)] | |
[BenchmarkCategory(MultipleChannels)] | |
public void MVVM_MultipleChannels() | |
{ | |
var a = this.a; | |
var b = this.b; | |
var c = this.c; | |
var d = this.d; | |
for (int i = NumberOfIterations; i > 0; i--) | |
{ | |
this.mvvmLightMessenger.Send(a, nameof(A)); | |
this.mvvmLightMessenger.Send(a, nameof(B)); | |
this.mvvmLightMessenger.Send(a, nameof(C)); | |
this.mvvmLightMessenger.Send(a, nameof(D)); | |
this.mvvmLightMessenger.Send(b, nameof(A)); | |
this.mvvmLightMessenger.Send(b, nameof(B)); | |
this.mvvmLightMessenger.Send(b, nameof(C)); | |
this.mvvmLightMessenger.Send(b, nameof(D)); | |
this.mvvmLightMessenger.Send(c, nameof(A)); | |
this.mvvmLightMessenger.Send(c, nameof(B)); | |
this.mvvmLightMessenger.Send(c, nameof(C)); | |
this.mvvmLightMessenger.Send(c, nameof(D)); | |
this.mvvmLightMessenger.Send(d, nameof(A)); | |
this.mvvmLightMessenger.Send(d, nameof(B)); | |
this.mvvmLightMessenger.Send(d, nameof(C)); | |
this.mvvmLightMessenger.Send(d, nameof(D)); | |
} | |
} | |
[Benchmark] | |
[BenchmarkCategory(MultipleChannels)] | |
public void WCT_MultipleChannels() | |
{ | |
var a = this.a; | |
var b = this.b; | |
var c = this.c; | |
var d = this.d; | |
for (int i = NumberOfIterations; i > 0; i--) | |
{ | |
this.wctMessenger.Send(a, nameof(A)); | |
this.wctMessenger.Send(a, nameof(B)); | |
this.wctMessenger.Send(a, nameof(C)); | |
this.wctMessenger.Send(a, nameof(D)); | |
this.wctMessenger.Send(b, nameof(A)); | |
this.wctMessenger.Send(b, nameof(B)); | |
this.wctMessenger.Send(b, nameof(C)); | |
this.wctMessenger.Send(b, nameof(D)); | |
this.wctMessenger.Send(c, nameof(A)); | |
this.wctMessenger.Send(c, nameof(B)); | |
this.wctMessenger.Send(c, nameof(C)); | |
this.wctMessenger.Send(c, nameof(D)); | |
this.wctMessenger.Send(d, nameof(A)); | |
this.wctMessenger.Send(d, nameof(B)); | |
this.wctMessenger.Send(d, nameof(C)); | |
this.wctMessenger.Send(d, nameof(D)); | |
} | |
} | |
} | |
public sealed class Recipient : IMessageSubscriber<A>, IMessageSubscriber<B>, IMessageSubscriber<C>, IMessageSubscriber<D> | |
{ | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public void ReceiveMessage<T>(T message) | |
{ | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public Task ReceiveMessageAsync(A message) | |
{ | |
return Task.CompletedTask; | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public Task ReceiveMessageAsync(B message) | |
{ | |
return Task.CompletedTask; | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public Task ReceiveMessageAsync(C message) | |
{ | |
return Task.CompletedTask; | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public Task ReceiveMessageAsync(D message) | |
{ | |
return Task.CompletedTask; | |
} | |
} | |
public class A { } | |
public class B { } | |
public class C { } | |
public class D { } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment