diff --git a/src/benchmark/Akka.Benchmarks/Dispatch/DispatcherBenchmarks.cs b/src/benchmark/Akka.Benchmarks/Dispatch/DispatcherBenchmarks.cs
new file mode 100644
index 00000000000..69b43364178
--- /dev/null
+++ b/src/benchmark/Akka.Benchmarks/Dispatch/DispatcherBenchmarks.cs
@@ -0,0 +1,121 @@
+// //-----------------------------------------------------------------------
+// //
+// // Copyright (C) 2009-2022 Lightbend Inc.
+// // Copyright (C) 2013-2022 .NET Foundation
+// //
+// //-----------------------------------------------------------------------
+
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Akka.Actor;
+using Akka.Benchmarks.Configurations;
+using Akka.Configuration;
+using Akka.Dispatch;
+using BenchmarkDotNet.Attributes;
+using IRunnable = Akka.Dispatch.IRunnable;
+
+namespace Akka.Benchmarks.Dispatch
+{
+ ///
+ /// Used to test the performance of various dispatchers
+ ///
+ [Config(typeof(MicroBenchmarkConfig))]
+ public class DispatcherBenchmarks
+ {
+ private ActorSystem _sys;
+ private DefaultDispatcherPrerequisites _prereqs;
+
+ private MessageDispatcher _dispatcher;
+
+ [Params(1_000_000)] // higher values will cause the CallingThreadDispatcher to stack overflow
+ public int TaskCount { get; set; }
+
+ [ParamsSource(nameof(AllConfigurators))]
+ public DispatcherConfig Configurator { get; set; }
+
+ public class DispatcherConfig
+ {
+ public DispatcherConfig(Config config, string name)
+ {
+ Config = config;
+ Name = name;
+ }
+
+ public Config Config { get; }
+
+ public string Name { get; }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+
+ private static readonly Config DefaultConfig = Akka.Remote.Configuration.RemoteConfigFactory.Default()
+ .WithFallback(Akka.Configuration.ConfigurationFactory.Default());
+
+ public IEnumerable AllConfigurators()
+ {
+ yield return new DispatcherConfig(DefaultConfig.GetConfig("akka.actor.default-dispatcher"), "DefaultThreadPool");
+ yield return new DispatcherConfig(DefaultConfig.GetConfig("akka.actor.internal-dispatcher"), "ForkJoin(sys)");
+ yield return new DispatcherConfig(DefaultConfig.GetConfig("akka.remote.default-remote-dispatcher"), "ForkJoin(remote)");
+ yield return new DispatcherConfig(@" executor = channel-executor
+ throughput=30", "ChannelD");
+ yield return new DispatcherConfig(@" executor = task-executor
+ throughput=30", "TaskD");
+ }
+
+ private TaskCompletionSource _tcs;
+
+ public sealed class RunnableTarget : IRunnable
+ {
+ private readonly TaskCompletionSource _tcs;
+ private readonly int _target;
+ private int _counter = 0;
+
+ public RunnableTarget(TaskCompletionSource tcs, int target)
+ {
+ _tcs = tcs;
+ _target = target;
+ }
+
+ public void Run()
+ {
+ if (Interlocked.Increment(ref _counter) >= _target)
+ {
+ _tcs.TrySetResult(_counter);
+ }
+ }
+ }
+
+ private RunnableTarget _runnable;
+
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _sys = ActorSystem.Create("Bench");
+ _prereqs = new DefaultDispatcherPrerequisites(_sys.EventStream, _sys.Scheduler, _sys.Settings,
+ _sys.Mailboxes);
+ var configurator = new DispatcherConfigurator(Configurator.Config, _prereqs);
+ _dispatcher = configurator.Dispatcher();
+ _tcs = new TaskCompletionSource();
+ _runnable = new RunnableTarget(_tcs, TaskCount);
+ }
+
+ [GlobalCleanup]
+ public void CleanUp()
+ {
+ _sys.Terminate().Wait();
+ }
+
+ [Benchmark]
+ public async Task RunDispatcher()
+ {
+ for (var i = 0; i < TaskCount; i++)
+ _dispatcher.Schedule(_runnable);
+ await _tcs.Task;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/benchmark/Akka.Benchmarks/Dispatch/MailboxThroughputBenchmarks.cs b/src/benchmark/Akka.Benchmarks/Dispatch/MailboxThroughputBenchmarks.cs
index e9a118d622e..06aa8b7b955 100644
--- a/src/benchmark/Akka.Benchmarks/Dispatch/MailboxThroughputBenchmarks.cs
+++ b/src/benchmark/Akka.Benchmarks/Dispatch/MailboxThroughputBenchmarks.cs
@@ -69,6 +69,12 @@ public void Setup()
_msg = new Envelope("hit", ActorRefs.NoSender);
}
+ [GlobalCleanup]
+ public void CleanUp()
+ {
+ _system.Terminate().Wait();
+ }
+
[IterationSetup]
public void IterationSetup()
{