From ef186a417e426b136da3b6392bed895d618f9ff1 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 6 Oct 2022 10:49:54 -0500 Subject: [PATCH] added actor messaging pressure benchmark (#6147) purpose of this benchmark is not to measure processing time - it's meant to measure allocation pressure created by Akka.NET infrastructure: * `Envelope`s * `Mailbox` and `MessageDispatcher` overhead * `ActorCell` and `ActorBase` invocation overhead Ideally the memory pressure, given a `const string` as messaging input, should be close to zero - but between mailbox queue segment allocations, delegate + closure allocations, and probably some boxing we know that's not the case. Purpose of this benchmark is to measure that impact across threads. --- .../ActorMessagingMemoryPressureBenchmark.cs | 91 +++++++++++++++++++ .../Akka.Benchmarks/Actor/FsmBenchmarks.cs | 4 +- 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs diff --git a/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs new file mode 100644 index 00000000000..d025604c158 --- /dev/null +++ b/src/benchmark/Akka.Benchmarks/Actor/ActorMessagingMemoryPressureBenchmark.cs @@ -0,0 +1,91 @@ +// //----------------------------------------------------------------------- +// // +// // Copyright (C) 2009-2022 Lightbend Inc. +// // Copyright (C) 2013-2022 .NET Foundation +// // +// //----------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Benchmarks.Configurations; +using Akka.Routing; +using BenchmarkDotNet.Attributes; + +namespace Akka.Benchmarks.Actor +{ + [Config(typeof(MicroBenchmarkConfig))] + public class ActorMessagingMemoryPressureBenchmark + { + #region Classes + public sealed class StopActor + { + private StopActor(){} + public static readonly StopActor Instance = new StopActor(); + } + + public sealed class MyActor : ReceiveActor + { + public MyActor() + { + Receive(str => + { + Context.Stop(Self); + Sender.Tell(str); + }); + + Receive(str => + { + Sender.Tell(str); + }); + } + } + #endregion + + private ActorSystem _sys; + private IActorRef _actorEntryPoint; + + private const string Msg = "hit"; + + [Params(100_000)] + public int MsgCount { get; set; } + + [Params(10, 100)] + public int ActorCount { get; set; } + + [GlobalSetup] + public void Setup() + { + _sys = ActorSystem.Create("Bench", @"akka.log-dead-letters = off"); + } + + [GlobalCleanup] + public async Task CleanUp() + { + await _sys.Terminate(); + } + + [IterationCleanup] + public void PerInvokeCleanup() + { + _actorEntryPoint.GracefulStop(TimeSpan.FromSeconds(5)).Wait(); + } + + [IterationSetup] + public void PerInvokeSetup() + { + _actorEntryPoint = _sys.ActorOf(Props.Create().WithRouter(new BroadcastPool(ActorCount))); + } + + [Benchmark] + public Task PushMsgs() + { + for (var i = 0; i < MsgCount; i++) + { + _actorEntryPoint.Tell(Msg); + } + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/benchmark/Akka.Benchmarks/Actor/FsmBenchmarks.cs b/src/benchmark/Akka.Benchmarks/Actor/FsmBenchmarks.cs index fe61c667618..a4618411f70 100644 --- a/src/benchmark/Akka.Benchmarks/Actor/FsmBenchmarks.cs +++ b/src/benchmark/Akka.Benchmarks/Actor/FsmBenchmarks.cs @@ -118,9 +118,9 @@ public void Setup() } [GlobalCleanup] - public void CleanUp() + public async Task CleanUp() { - _sys.Terminate().Wait(); + await _sys.Terminate(); } [Benchmark]