From 8843a211675bb3743c8055150f6070aae3feab35 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Wed, 10 Jul 2024 12:44:51 -0500 Subject: [PATCH] Akka.Cluster: `ClusterMessageSerializer` benchmarks (#7280) * added benchmark for measuring Akka.Cluster serialization * formatting * added API approvals --- .../Akka.Cluster.Benchmarks.csproj | 3 + .../ClusterMessageSerializerBenchmarks.cs | 137 ++++++++++++++++++ ...APISpec.ApproveCluster.DotNet.verified.txt | 1 + ...oreAPISpec.ApproveCluster.Net.verified.txt | 1 + src/core/Akka.Cluster/Member.cs | 1 - .../Akka.Cluster/Properties/AssemblyInfo.cs | 1 + 6 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/benchmark/Akka.Cluster.Benchmarks/Serialization/ClusterMessageSerializerBenchmarks.cs diff --git a/src/benchmark/Akka.Cluster.Benchmarks/Akka.Cluster.Benchmarks.csproj b/src/benchmark/Akka.Cluster.Benchmarks/Akka.Cluster.Benchmarks.csproj index 958d31ecdd7..920d96fc073 100644 --- a/src/benchmark/Akka.Cluster.Benchmarks/Akka.Cluster.Benchmarks.csproj +++ b/src/benchmark/Akka.Cluster.Benchmarks/Akka.Cluster.Benchmarks.csproj @@ -15,6 +15,9 @@ + + TestMember.cs + Configs.cs diff --git a/src/benchmark/Akka.Cluster.Benchmarks/Serialization/ClusterMessageSerializerBenchmarks.cs b/src/benchmark/Akka.Cluster.Benchmarks/Serialization/ClusterMessageSerializerBenchmarks.cs new file mode 100644 index 00000000000..9e3e8fb3adc --- /dev/null +++ b/src/benchmark/Akka.Cluster.Benchmarks/Serialization/ClusterMessageSerializerBenchmarks.cs @@ -0,0 +1,137 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2009-2024 Lightbend Inc. +// Copyright (C) 2013-2024 .NET Foundation +// +// ----------------------------------------------------------------------- + +using System.Collections.Immutable; +using Akka.Actor; +using Akka.Benchmarks.Configurations; +using Akka.Cluster.Serialization; +using Akka.Cluster.Tests; +using Akka.Util; +using BenchmarkDotNet.Attributes; + +namespace Akka.Cluster.Benchmarks.Serialization; + +[Config(typeof(MicroBenchmarkConfig))] +public class ClusterMessageSerializerBenchmarks +{ + private ExtendedActorSystem _system; + private ClusterMessageSerializer _clusterMessageSerializer; + + private static readonly Member A1 = TestMember.Create(new Address("akka.tcp", "sys", "a", 2552), + MemberStatus.Joining, appVersion: AppVersion.Create("1.0.0")); + + private static readonly Member B1 = TestMember.Create(new Address("akka.tcp", "sys", "b", 2552), MemberStatus.Up, + ImmutableHashSet.Create("r1"), appVersion: AppVersion.Create("1.1.0")); + + private static readonly Member C1 = TestMember.Create(new Address("akka.tcp", "sys", "c", 2552), + MemberStatus.Leaving, ImmutableHashSet.Create("r2"), appVersion: AppVersion.Create("1.1.0")); + + private static readonly Member D1 = TestMember.Create(new Address("akka.tcp", "sys", "d", 2552), + MemberStatus.Exiting, ImmutableHashSet.Create("r1", "r2")); + + private static readonly Member E1 = TestMember.Create(new Address("akka.tcp", "sys", "e", 2552), MemberStatus.Down, + ImmutableHashSet.Create("r3")); + + [GlobalSetup] + public void Setup() + { + _system = (ExtendedActorSystem)ActorSystem.Create("system", "akka.actor.provider=cluster"); + _clusterMessageSerializer = new ClusterMessageSerializer(_system); + } + + private static readonly ClusterHeartbeatSender.Heartbeat Heartbeat = new(A1.UniqueAddress.Address, 10, 3); + + private static readonly ClusterHeartbeatSender.HeartbeatRsp HeartbeatRsp = new(B1.UniqueAddress, 10, 3); + + [Benchmark] + public byte[] Serialize_Heartbeat() + { + return _clusterMessageSerializer.ToBinary(Heartbeat); + } + + [Benchmark] + public object Deserialize_Heartbeat() + { + return _clusterMessageSerializer.FromBinary(_clusterMessageSerializer.ToBinary(Heartbeat), + _clusterMessageSerializer.Manifest(Heartbeat)); + } + + [Benchmark] + public byte[] Serialize_HeartbeatRsp() + { + return _clusterMessageSerializer.ToBinary(HeartbeatRsp); + } + + [Benchmark] + public object Deserialize_HeartbeatRsp() + { + return _clusterMessageSerializer.FromBinary(_clusterMessageSerializer.ToBinary(HeartbeatRsp), + _clusterMessageSerializer.Manifest(HeartbeatRsp)); + } + + private static readonly GossipEnvelope GossipEnvelope = new(A1.UniqueAddress, C1.UniqueAddress, + new Gossip(ImmutableSortedSet.Create(A1, B1, C1, D1)).Increment(new VectorClock.Node("node1")) + .Increment(new VectorClock.Node("node2")) + .Seen(A1.UniqueAddress) + .Seen(B1.UniqueAddress)); + private static readonly Gossip Gossip2 = GossipEnvelope.Gossip + .Increment(new VectorClock.Node("node3")) + .Increment(new VectorClock.Node("node4")) + .Seen(A1.UniqueAddress).Seen(C1.UniqueAddress); + private static readonly Reachability Reachability = Reachability.Empty.Unreachable(A1.UniqueAddress, E1.UniqueAddress).Unreachable(B1.UniqueAddress, E1.UniqueAddress); + + private static readonly Gossip Gossip3 = Gossip2.Copy(ImmutableSortedSet.Create(A1, B1, C1, D1, E1), + overview: Gossip2.Overview.Copy(reachability: Reachability)); + + private static readonly GossipStatus GossipStatus = new(A1.UniqueAddress, Gossip3.Version); + private static readonly InternalClusterAction.Welcome Welcome = new(A1.UniqueAddress, Gossip3); + + [Benchmark] + public byte[] Serialize_GossipEnvelope() + { + return _clusterMessageSerializer.ToBinary(GossipEnvelope); + } + + [Benchmark] + public object Deserialize_GossipEnvelope() + { + return _clusterMessageSerializer.FromBinary(_clusterMessageSerializer.ToBinary(GossipEnvelope), + _clusterMessageSerializer.Manifest(GossipEnvelope)); + } + + [Benchmark] + public byte[] Serialize_GossipStatus() + { + return _clusterMessageSerializer.ToBinary(GossipStatus); + } + + [Benchmark] + public object Deserialize_GossipStatus() + { + return _clusterMessageSerializer.FromBinary(_clusterMessageSerializer.ToBinary(GossipStatus), + _clusterMessageSerializer.Manifest(GossipStatus)); + } + + [Benchmark] + public byte[] Serialize_Welcome() + { + return _clusterMessageSerializer.ToBinary(Welcome); + } + + [Benchmark] + public object Deserialize_Welcome() + { + return _clusterMessageSerializer.FromBinary(_clusterMessageSerializer.ToBinary(Welcome), + _clusterMessageSerializer.Manifest(Welcome)); + } + + [GlobalCleanup] + public void Cleanup() + { + _system.Dispose(); + } +} \ No newline at end of file diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt index 5ba6c794e8f..38b3fc8834f 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt @@ -1,5 +1,6 @@ [assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/akkadotnet/akka.net")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Benchmarks")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Benchmarks")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Metrics")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Sharding")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Sharding.Tests")] diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt index 60b87ce8f06..f9aa7b26004 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt @@ -1,5 +1,6 @@ [assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/akkadotnet/akka.net")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Benchmarks")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Benchmarks")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Metrics")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Sharding")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Sharding.Tests")] diff --git a/src/core/Akka.Cluster/Member.cs b/src/core/Akka.Cluster/Member.cs index 3846f15fb1e..1abd73d5873 100644 --- a/src/core/Akka.Cluster/Member.cs +++ b/src/core/Akka.Cluster/Member.cs @@ -11,7 +11,6 @@ using System.Linq; using Akka.Actor; using Akka.Util; -using Akka.Util.Internal; using Newtonsoft.Json; namespace Akka.Cluster diff --git a/src/core/Akka.Cluster/Properties/AssemblyInfo.cs b/src/core/Akka.Cluster/Properties/AssemblyInfo.cs index 79c187f727b..b157afe7792 100644 --- a/src/core/Akka.Cluster/Properties/AssemblyInfo.cs +++ b/src/core/Akka.Cluster/Properties/AssemblyInfo.cs @@ -12,6 +12,7 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: InternalsVisibleTo("Akka.Cluster.Tests")] +[assembly: InternalsVisibleTo("Akka.Cluster.Benchmarks")] [assembly: InternalsVisibleTo("Akka.Cluster.Tests.MultiNode")] [assembly: InternalsVisibleTo("Akka.Cluster.Tests.Performance")] [assembly: InternalsVisibleTo("Akka.Cluster.TestKit")]