From c9d172e32380001868f249b3cb6b91a1969916e2 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Mon, 10 Jun 2024 16:20:17 -0500 Subject: [PATCH 01/10] added baseline for measuring Ask vs. Tell memory pressure --- .../ActorMessagingMemoryPressureBenchmark.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index c98487a8021..6854315f07f 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -52,6 +52,8 @@ public MyActor() [Params(10, 100)] public int ActorCount { get; set; } + + private Task[] _askTasks; [GlobalSetup] public void Setup() @@ -75,9 +77,10 @@ public void PerInvokeCleanup() public void PerInvokeSetup() { _actorEntryPoint = _sys.ActorOf(Props.Create().WithRouter(new BroadcastPool(ActorCount))); + _askTasks = new Task[MsgCount]; } - [Benchmark] + [Benchmark(Baseline = true)] public Task PushMsgs() { for (var i = 0; i < MsgCount; i++) @@ -87,5 +90,17 @@ public Task PushMsgs() return Task.CompletedTask; } + + [Benchmark] + public Task AskMsgs() + { + for (var i = 0; i < MsgCount; i++) + { + _askTasks[i] = _actorEntryPoint.Ask(Msg); + } + + _actorEntryPoint.Tell(StopActor.Instance); + return Task.WhenAll(_askTasks); + } } } From 65e6faad089af1494d011130f88cfbae6ccfca03 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Mon, 10 Jun 2024 16:21:12 -0500 Subject: [PATCH 02/10] remove unnecessary cleanup --- .../Actor/ActorMessagingMemoryPressureBenchmark.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index 6854315f07f..50f443cefe4 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -98,8 +98,7 @@ public Task AskMsgs() { _askTasks[i] = _actorEntryPoint.Ask(Msg); } - - _actorEntryPoint.Tell(StopActor.Instance); + return Task.WhenAll(_askTasks); } } From 4863ca83ff7ccabbbfd0bbdce220dbca94f21856 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Mon, 10 Jun 2024 16:30:09 -0500 Subject: [PATCH 03/10] made it easier to understand requests / second --- .../Actor/ActorMessagingMemoryPressureBenchmark.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index 50f443cefe4..09d6bf63cfa 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -14,7 +14,7 @@ namespace Akka.Benchmarks.Actor { - [Config(typeof(MicroBenchmarkConfig))] + [Config(typeof(MonitoringConfig))] public class ActorMessagingMemoryPressureBenchmark { #region Classes @@ -46,9 +46,8 @@ public MyActor() private IActorRef _actorEntryPoint; private const string Msg = "hit"; - - [Params(100_000)] - public int MsgCount { get; set; } + + public const int MsgCount = 100_000; [Params(10, 100)] public int ActorCount { get; set; } @@ -80,7 +79,7 @@ public void PerInvokeSetup() _askTasks = new Task[MsgCount]; } - [Benchmark(Baseline = true)] + [Benchmark(Baseline = true, OperationsPerInvoke = MsgCount)] public Task PushMsgs() { for (var i = 0; i < MsgCount; i++) @@ -91,7 +90,7 @@ public Task PushMsgs() return Task.CompletedTask; } - [Benchmark] + [Benchmark(OperationsPerInvoke = MsgCount)] public Task AskMsgs() { for (var i = 0; i < MsgCount; i++) From 9a2a08316d5a6e10c68a487cf96fd3f453638c0f Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 16:44:47 -0500 Subject: [PATCH 04/10] add more appropriate settings for Ask vs. Tell benchmarking in BDN --- .../ActorMessagingMemoryPressureBenchmark.cs | 65 ++++++++++++++----- .../Akka.Benchmarks/Configurations/Configs.cs | 17 +++++ 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index 09d6bf63cfa..cce89c49f55 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)] 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() { @@ -75,30 +101,33 @@ public void PerInvokeCleanup() [IterationSetup] public void PerInvokeSetup() { + _taskCompletionSource = new TaskCompletionSource(); _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..48797700dca 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -10,7 +10,9 @@ 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 +80,19 @@ public MonitoringConfig() AddColumn(new RequestsPerSecondColumn()); } } + + public class MacroBenchmarkConfig : ManualConfig + { + public MacroBenchmarkConfig() + { + AddExporter(MarkdownExporter.GitHub); + AddColumn(new RequestsPerSecondColumn()); + AddJob(Job.LongRun + .WithGcMode(new GcMode { Server = true, Concurrent = true }) + .WithWarmupCount(10) + .WithIterationCount(25) + .RunOncePerIteration() + .WithStrategy(RunStrategy.Monitoring)); + } + } } From 537c189cb143c6c7514e0a2892d63e5fbd327150 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 16:49:32 -0500 Subject: [PATCH 05/10] disable processor affinity --- src/benchmark/Akka.Benchmarks/Configurations/Configs.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs index 48797700dca..74d781f9197 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -5,6 +5,7 @@ // //----------------------------------------------------------------------- +using System; using System.Reflection; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Columns; @@ -92,7 +93,8 @@ public MacroBenchmarkConfig() .WithWarmupCount(10) .WithIterationCount(25) .RunOncePerIteration() - .WithStrategy(RunStrategy.Monitoring)); + .WithStrategy(RunStrategy.Monitoring) + .WithAffinity(IntPtr.Zero)); } } } From 77c01aec37c29b9eec539b8bb85c6042be51b1a7 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 16:56:01 -0500 Subject: [PATCH 06/10] added support for just running a single actor --- .../Actor/ActorMessagingMemoryPressureBenchmark.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index cce89c49f55..aab4ff4eed5 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -75,7 +75,7 @@ protected override void OnReceive(object message) public const int MsgCount = 100_000; - [Params(10, 100)] + [Params(1, 10, 100)] public int ActorCount { get; set; } private Task[] _askTasks; @@ -96,13 +96,17 @@ public async Task CleanUp() public void PerInvokeCleanup() { _actorEntryPoint.GracefulStop(TimeSpan.FromSeconds(5)).Wait(); + _terminationActor.GracefulStop(TimeSpan.FromSeconds(5)).Wait(); } [IterationSetup] public void PerInvokeSetup() { _taskCompletionSource = new TaskCompletionSource(); - _actorEntryPoint = _sys.ActorOf(Props.Create().WithRouter(new BroadcastPool(ActorCount))); + 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]; From d550d50770a65bcd684919ecf4e95bdeaf77a711 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 16:56:32 -0500 Subject: [PATCH 07/10] testing --- src/benchmark/Akka.Benchmarks/Configurations/Configs.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs index 74d781f9197..5b6ccab616a 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -94,7 +94,8 @@ public MacroBenchmarkConfig() .WithIterationCount(25) .RunOncePerIteration() .WithStrategy(RunStrategy.Monitoring) - .WithAffinity(IntPtr.Zero)); + //.WithAffinity(IntPtr.Zero) + ); } } } From 29394bdeb60dda642407d681b06bbc3578444a16 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 16:58:07 -0500 Subject: [PATCH 08/10] increase warmup and iteration count significantly --- src/benchmark/Akka.Benchmarks/Configurations/Configs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs index 5b6ccab616a..e478b429a36 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -90,8 +90,8 @@ public MacroBenchmarkConfig() AddColumn(new RequestsPerSecondColumn()); AddJob(Job.LongRun .WithGcMode(new GcMode { Server = true, Concurrent = true }) - .WithWarmupCount(10) - .WithIterationCount(25) + .WithWarmupCount(25) + .WithIterationCount(50) .RunOncePerIteration() .WithStrategy(RunStrategy.Monitoring) //.WithAffinity(IntPtr.Zero) From 9203d992ddbb67ec9d562d9962ed2369cf406a33 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 19:02:54 -0500 Subject: [PATCH 09/10] disable affinity mask for macrobenchmarks --- src/benchmark/Akka.Benchmarks/Configurations/Configs.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs index e478b429a36..46778f6d6fb 100644 --- a/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs +++ b/src/benchmark/Akka.Benchmarks/Configurations/Configs.cs @@ -86,6 +86,10 @@ 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 @@ -94,7 +98,7 @@ public MacroBenchmarkConfig() .WithIterationCount(50) .RunOncePerIteration() .WithStrategy(RunStrategy.Monitoring) - //.WithAffinity(IntPtr.Zero) + .WithAffinity(affinityMask) ); } } From f63c1512ca6843bdd75b9f11742db539c146778e Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Jun 2024 19:59:57 -0500 Subject: [PATCH 10/10] fixed merge conflict --- .../Actor/ActorMessagingMemoryPressureBenchmark.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs index b7ded924acf..aab4ff4eed5 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -133,16 +133,5 @@ public Task AskMsgs() return Task.WhenAll(_askTasks); } - - [Benchmark(OperationsPerInvoke = MsgCount)] - 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