diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index 09d6bf63cfa..aab4ff4eed5 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -11,19 +11,24 @@ using Akka.Benchmarks.Configurations; using Akka.Routing; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; namespace Akka.Benchmarks.Actor { - [Config(typeof(MonitoringConfig))] + [Config(typeof(MacroBenchmarkConfig))] public class ActorMessagingMemoryPressureBenchmark { #region Classes + public sealed class StopActor { - private StopActor(){} + private StopActor() + { + } + public static readonly StopActor Instance = new(); } - + public sealed class MyActor : ReceiveActor { public MyActor() @@ -33,33 +38,54 @@ public MyActor() Context.Stop(Self); Sender.Tell(str); }); - - Receive(str => + + Receive(str => { Sender.Tell(str); }); + } + } + + public sealed class TerminationActor : UntypedActor + { + private int _remainingMessages; + private readonly TaskCompletionSource _taskCompletionSource; + + public TerminationActor(TaskCompletionSource taskCompletionSource, + int remainingMessages) + { + _taskCompletionSource = taskCompletionSource; + _remainingMessages = remainingMessages; + } + + protected override void OnReceive(object message) + { + if (--_remainingMessages == 0) { - Sender.Tell(str); - }); + _taskCompletionSource.SetResult(); + } } } + #endregion - + private ActorSystem _sys; private IActorRef _actorEntryPoint; + private IActorRef _terminationActor; + private TaskCompletionSource _taskCompletionSource; private const string Msg = "hit"; public const int MsgCount = 100_000; - - [Params(10, 100)] + + [Params(1, 10, 100)] public int ActorCount { get; set; } private Task[] _askTasks; - + [GlobalSetup] public void Setup() { _sys = ActorSystem.Create("Bench", @"akka.log-dead-letters = off"); } - + [GlobalCleanup] public async Task CleanUp() { @@ -70,35 +96,42 @@ public async Task CleanUp() public void PerInvokeCleanup() { _actorEntryPoint.GracefulStop(TimeSpan.FromSeconds(5)).Wait(); + _terminationActor.GracefulStop(TimeSpan.FromSeconds(5)).Wait(); } [IterationSetup] public void PerInvokeSetup() { - _actorEntryPoint = _sys.ActorOf(Props.Create().WithRouter(new BroadcastPool(ActorCount))); + _taskCompletionSource = new TaskCompletionSource(); + if(ActorCount == 1) + _actorEntryPoint = _sys.ActorOf(Props.Create()); + else if(ActorCount > 1) + _actorEntryPoint = _sys.ActorOf(Props.Create().WithRouter(new BroadcastPool(ActorCount))); + _terminationActor = _sys.ActorOf(Props.Create(() => + new TerminationActor(_taskCompletionSource, MsgCount))); _askTasks = new Task[MsgCount]; } - [Benchmark(Baseline = true, OperationsPerInvoke = MsgCount)] + [Benchmark(Baseline = true, OperationsPerInvoke = MsgCount * 2)] public Task PushMsgs() { for (var i = 0; i < MsgCount; i++) { - _actorEntryPoint.Tell(Msg); + _actorEntryPoint.Tell(Msg, _terminationActor); } - return Task.CompletedTask; + return _taskCompletionSource.Task; } - - [Benchmark(OperationsPerInvoke = MsgCount)] + + [Benchmark(OperationsPerInvoke = MsgCount * 2)] public Task AskMsgs() { for (var i = 0; i < MsgCount; i++) { _askTasks[i] = _actorEntryPoint.Ask(Msg); } - + return Task.WhenAll(_askTasks); } } -} +} \ No newline at end of file diff --git a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs index 28353207e6c..46778f6d6fb 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -5,12 +5,15 @@ // //----------------------------------------------------------------------- +using System; using System.Reflection; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Columns; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Engines; using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; @@ -78,4 +81,25 @@ public MonitoringConfig() AddColumn(new RequestsPerSecondColumn()); } } + + public class MacroBenchmarkConfig : ManualConfig + { + public MacroBenchmarkConfig() + { + int processorCount = Environment.ProcessorCount; + IntPtr affinityMask = (IntPtr)((1 << processorCount) - 1); + + + AddExporter(MarkdownExporter.GitHub); + AddColumn(new RequestsPerSecondColumn()); + AddJob(Job.LongRun + .WithGcMode(new GcMode { Server = true, Concurrent = true }) + .WithWarmupCount(25) + .WithIterationCount(50) + .RunOncePerIteration() + .WithStrategy(RunStrategy.Monitoring) + .WithAffinity(affinityMask) + ); + } + } }