Skip to content

Commit

Permalink
Merge pull request #5305 from akkadotnet/dev
Browse files Browse the repository at this point in the history
v1.4.27 Release
  • Loading branch information
Aaronontheweb authored Oct 11, 2021
2 parents 2f92a5a + e575a8a commit 193c74e
Show file tree
Hide file tree
Showing 30 changed files with 1,295 additions and 766 deletions.
76 changes: 76 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,79 @@
#### 1.4.27 October 11 2021 ####
**Maintenance Release for Akka.NET 1.4**
Akka.NET v1.4.27 is a small release that contains some _major_ performance improvements for Akka.Remote.

**Performance Fixes**
In [RemoteActorRefProvider address paring, caching and resolving improvements](https://github.com/akkadotnet/akka.net/pull/5273) Akka.NET contributor @Zetanova introduced some major changes that make the entire `ActorPath` class much more reusable and more parse-efficient.

Our last major round of Akka.NET performance improvements in Akka.NET v1.4.25 produced the following:

```
OSVersion: Microsoft Windows NT 6.2.9200.0
ProcessorCount: 16
ClockSpeed: 0 MHZ
Actor Count: 32
Messages sent/received per client: 200000 (2e5)
Is Server GC: True
Thread count: 111
Num clients, Total [msg], Msgs/sec, Total [ms]
1, 200000, 130634, 1531.54
5, 1000000, 246975, 4049.20
10, 2000000, 244499, 8180.16
15, 3000000, 244978, 12246.39
20, 4000000, 245159, 16316.37
25, 5000000, 243333, 20548.09
30, 6000000, 241644, 24830.55
```

In Akka.NET v1.4.27 those numbers now look like:

```
OSVersion: Microsoft Windows NT 6.2.9200.
ProcessorCount: 16
ClockSpeed: 0 MHZ
Actor Count: 32
Messages sent/received per client: 200000 (2e5)
Is Server GC: True
Thread count: 111
Num clients, Total [msg], Msgs/sec, Total [ms]
1, 200000, 105043, 1904.29
5, 1000000, 255494, 3914.73
10, 2000000, 291843, 6853.30
15, 3000000, 291291, 10299.75
20, 4000000, 286513, 13961.68
25, 5000000, 292569, 17090.64
30, 6000000, 281492, 21315.35
```

To put these numbers in comparison, here's what Akka.NET's performance looked like as of v1.4.0:

```
Num clients (actors) Total [msg] Msgs/sec Total [ms]
1 200000 69736 2868.60
5 1000000 141243 7080.98
10 2000000 136771 14623.27
15 3000000 38190 78556.49
20 4000000 32401 123454.60
25 5000000 33341 149967.08
30 6000000 126093 47584.92
```


We've made Akka.Remote consistently faster, more predictable, and reduced total memory consumption significantly in the process.


You can [see the full set of changes introduced in Akka.NET v1.4.27 here](https://github.com/akkadotnet/akka.net/milestone/57?closed=1)

| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 3 | 89 | 8 | Aaron Stannard |
| 1 | 856 | 519 | Andreas Dirnberger |
| 1 | 3 | 4 | Vadym Artemchuk |
| 1 | 261 | 233 | Gregorius Soedharmo |
| 1 | 1 | 1 | dependabot[bot] |

#### 1.4.26 September 28 2021 ####
**Maintenance Release for Akka.NET 1.4**
Akka.NET v1.4.26 is a very small release that addresses one wire format regression introduced in Akka.NET v1.4.20.
Expand Down
7 changes: 3 additions & 4 deletions docs/articles/actors/routers.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,10 +472,9 @@ var router = system.ActorOf(Props.Empty.WithRouter(new ScatterGatherFirstComplet

The `SmallestMailboxPool` router will send the message to the routee with fewest messages in mailbox. The selection is done in this order:

1. Pick any idle routee (not processing message) with empty mailbox
2. Pick any routee with empty mailbox
3. Pick routee with fewest pending messages in mailbox
4. Pick any remote routee, remote actors are consider lowest priority, since their mailbox size is unknown
1. Pick any routee with empty mailbox
2. Pick routee with fewest pending messages in mailbox
3. Pick any remote routee, remote actors are consider lowest priority, since their mailbox size is unknown

![SmallestMailbox Router](/images/SmallestMailbox.png)

Expand Down
65 changes: 62 additions & 3 deletions src/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<Copyright>Copyright © 2013-2021 Akka.NET Team</Copyright>
<Authors>Akka.NET Team</Authors>
<VersionPrefix>1.4.23</VersionPrefix>
<VersionPrefix>1.4.27</VersionPrefix>
<PackageIconUrl>https://getakka.net/images/akkalogo.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/akkadotnet/akka.net</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/akkadotnet/akka.net/blob/master/LICENSE</PackageLicenseUrl>
Expand All @@ -11,7 +11,7 @@
<PropertyGroup>
<XunitVersion>2.4.1</XunitVersion>
<TestSdkVersion>16.11.0</TestSdkVersion>
<HyperionVersion>0.11.1</HyperionVersion>
<HyperionVersion>0.11.2</HyperionVersion>
<NewtonsoftJsonVersion>[12.0.3,)</NewtonsoftJsonVersion>
<NBenchVersion>2.0.1</NBenchVersion>
<ProtobufVersion>3.17.3</ProtobufVersion>
Expand All @@ -30,7 +30,66 @@
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<PropertyGroup>
<PackageReleaseNotes>Placeholder for nightlies**</PackageReleaseNotes>
<PackageReleaseNotes>Maintenance Release for Akka.NET 1.4**
Akka.NET v1.4.27 is a small release that contains some _major_ performance improvements for Akka.Remote.
Performance Fixes**
In [RemoteActorRefProvider address paring, caching and resolving improvements](https://github.com/akkadotnet/akka.net/pull/5273) Akka.NET contributor @Zetanova introduced some major changes that make the entire `ActorPath` class much more reusable and more parse-efficient.
Our last major round of Akka.NET performance improvements in Akka.NET v1.4.25 produced the following:
```
OSVersion: Microsoft Windows NT 6.2.9200.0
ProcessorCount: 16
ClockSpeed: 0 MHZ
Actor Count: 32
Messages sent/received per client: 200000 (2e5)
Is Server GC: True
Thread count: 111
Num clients, Total [msg], Msgs/sec, Total [ms]
1, 200000, 130634, 1531.54
5, 1000000, 246975, 4049.20
10, 2000000, 244499, 8180.16
15, 3000000, 244978, 12246.39
20, 4000000, 245159, 16316.37
25, 5000000, 243333, 20548.09
30, 6000000, 241644, 24830.55
```
In Akka.NET v1.4.27 those numbers now look like:
```
OSVersion: Microsoft Windows NT 6.2.9200.
ProcessorCount: 16
ClockSpeed: 0 MHZ
Actor Count: 32
Messages sent/received per client: 200000 (2e5)
Is Server GC: True
Thread count: 111
Num clients, Total [msg], Msgs/sec, Total [ms]
1, 200000, 105043, 1904.29
5, 1000000, 255494, 3914.73
10, 2000000, 291843, 6853.30
15, 3000000, 291291, 10299.75
20, 4000000, 286513, 13961.68
25, 5000000, 292569, 17090.64
30, 6000000, 281492, 21315.35
```
To put these numbers in comparison, here's what Akka.NET's performance looked like as of v1.4.0:
```
Num clients (actors) Total [msg] Msgs/sec Total [ms]
1 200000 69736 2868.60
5 1000000 141243 7080.98
10 2000000 136771 14623.27
15 3000000 38190 78556.49
20 4000000 32401 123454.60
25 5000000 33341 149967.08
30 6000000 126093 47584.92
```
We've made Akka.Remote consistently faster, more predictable, and reduced total memory consumption significantly in the process.
You can [see the full set of changes introduced in Akka.NET v1.4.27 here](https://github.com/akkadotnet/akka.net/milestone/57?closed=1)
| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 3 | 89 | 8 | Aaron Stannard |
| 1 | 856 | 519 | Andreas Dirnberger |
| 1 | 3 | 4 | Vadym Artemchuk |
| 1 | 261 | 233 | Gregorius Soedharmo |
| 1 | 1 | 1 | dependabot[bot] |</PackageReleaseNotes>
</PropertyGroup>
<!-- SourceLink support for all Akka.NET projects -->
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System;
using Akka.Actor;
using Akka.Configuration;
using Akka.Configuration;

namespace Akka.Cluster.Metrics
{
Expand Down
44 changes: 23 additions & 21 deletions src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,21 @@ namespace Akka.Actor
protected ActorPath(Akka.Actor.Address address, string name) { }
protected ActorPath(Akka.Actor.ActorPath parentPath, string name, long uid) { }
public Akka.Actor.Address Address { get; }
public abstract System.Collections.Generic.IReadOnlyList<string> Elements { get; }
public int Depth { get; }
public System.Collections.Generic.IReadOnlyList<string> Elements { get; }
public string Name { get; }
public abstract Akka.Actor.ActorPath Parent { get; }
public abstract Akka.Actor.ActorPath Root { get; }
public Akka.Actor.ActorPath Parent { get; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public Akka.Actor.ActorPath Root { get; }
public long Uid { get; }
public Akka.Actor.ActorPath Child(string childName) { }
public abstract int CompareTo(Akka.Actor.ActorPath other);
public int CompareTo(Akka.Actor.ActorPath other) { }
public bool Equals(Akka.Actor.ActorPath other) { }
public override bool Equals(object obj) { }
public static string FormatPathElements(System.Collections.Generic.IEnumerable<string> pathElements) { }
public override int GetHashCode() { }
public static bool IsValidPathElement(string s) { }
public Akka.Actor.ActorPath ParentOf(int depth) { }
public static Akka.Actor.ActorPath Parse(string path) { }
public string ToSerializationFormat() { }
public string ToSerializationFormatWithAddress(Akka.Actor.Address address) { }
Expand All @@ -199,13 +202,17 @@ namespace Akka.Actor
public string ToStringWithoutAddress() { }
public Akka.Util.ISurrogate ToSurrogate(Akka.Actor.ActorSystem system) { }
public static bool TryParse(string path, out Akka.Actor.ActorPath actorPath) { }
public static bool TryParse(Akka.Actor.ActorPath basePath, string absoluteUri, out Akka.Actor.ActorPath actorPath) { }
public static bool TryParse(Akka.Actor.ActorPath basePath, System.ReadOnlySpan<char> absoluteUri, out Akka.Actor.ActorPath actorPath) { }
public static bool TryParseAddress(string path, out Akka.Actor.Address address) { }
public abstract Akka.Actor.ActorPath WithUid(long uid);
public static bool TryParseAddress(string path, out Akka.Actor.Address address, out System.ReadOnlySpan<char> absoluteUri) { }
public static bool TryParseParts(System.ReadOnlySpan<char> path, out System.ReadOnlySpan<char> address, out System.ReadOnlySpan<char> absoluteUri) { }
public Akka.Actor.ActorPath WithUid(long uid) { }
public static Akka.Actor.ActorPath /(Akka.Actor.ActorPath path, string name) { }
public static Akka.Actor.ActorPath /(Akka.Actor.ActorPath path, System.Collections.Generic.IEnumerable<string> name) { }
public static bool ==(Akka.Actor.ActorPath left, Akka.Actor.ActorPath right) { }
public static bool !=(Akka.Actor.ActorPath left, Akka.Actor.ActorPath right) { }
public class Surrogate : Akka.Util.ISurrogate, System.IEquatable<Akka.Actor.ActorPath.Surrogate>, System.IEquatable<Akka.Actor.ActorPath>
public sealed class Surrogate : Akka.Util.ISurrogate, System.IEquatable<Akka.Actor.ActorPath.Surrogate>, System.IEquatable<Akka.Actor.ActorPath>
{
public Surrogate(string path) { }
public string Path { get; }
Expand Down Expand Up @@ -408,13 +415,17 @@ namespace Akka.Actor
public static Akka.Actor.Address Parse(string address) { }
public override string ToString() { }
public Akka.Util.ISurrogate ToSurrogate(Akka.Actor.ActorSystem system) { }
public static bool TryParse(string path, out Akka.Actor.Address address) { }
public static bool TryParse(string path, out Akka.Actor.Address address, out string absolutUri) { }
public static bool TryParse(System.ReadOnlySpan<char> span, out Akka.Actor.Address address) { }
public static bool TryParse(System.ReadOnlySpan<char> span, out Akka.Actor.Address address, out System.ReadOnlySpan<char> absolutUri) { }
public Akka.Actor.Address WithHost(string host = null) { }
public Akka.Actor.Address WithPort(System.Nullable<int> port = null) { }
public Akka.Actor.Address WithProtocol(string protocol) { }
public Akka.Actor.Address WithSystem(string system) { }
public static bool ==(Akka.Actor.Address left, Akka.Actor.Address right) { }
public static bool !=(Akka.Actor.Address left, Akka.Actor.Address right) { }
public class AddressSurrogate : Akka.Util.ISurrogate
public sealed class AddressSurrogate : Akka.Util.ISurrogate
{
public AddressSurrogate() { }
public string Host { get; set; }
Expand Down Expand Up @@ -497,15 +508,9 @@ namespace Akka.Actor
{
public static void CancelIfNotNull(this Akka.Actor.ICancelable cancelable) { }
}
public class ChildActorPath : Akka.Actor.ActorPath
public sealed class ChildActorPath : Akka.Actor.ActorPath
{
public ChildActorPath(Akka.Actor.ActorPath parentPath, string name, long uid) { }
public override System.Collections.Generic.IReadOnlyList<string> Elements { get; }
public override Akka.Actor.ActorPath Parent { get; }
public override Akka.Actor.ActorPath Root { get; }
public override int CompareTo(Akka.Actor.ActorPath other) { }
public override int GetHashCode() { }
public override Akka.Actor.ActorPath WithUid(long uid) { }
}
public sealed class CoordinatedShutdown : Akka.Actor.IExtension
{
Expand Down Expand Up @@ -963,6 +968,8 @@ namespace Akka.Actor
Akka.Actor.IInternalActorRef TempContainer { get; }
System.Threading.Tasks.Task TerminationTask { get; }
Akka.Actor.IInternalActorRef ActorOf(Akka.Actor.Internal.ActorSystemImpl system, Akka.Actor.Props props, Akka.Actor.IInternalActorRef supervisor, Akka.Actor.ActorPath path, bool systemService, Akka.Actor.Deploy deploy, bool lookupDeploy, bool async);
[Akka.Annotations.InternalApiAttribute()]
Akka.Actor.FutureActorRef<T> CreateFutureRef<T>(System.Threading.Tasks.TaskCompletionSource<T> tcs);
Akka.Actor.Address GetExternalAddressFor(Akka.Actor.Address address);
void Init(Akka.Actor.Internal.ActorSystemImpl system);
void RegisterTempActor(Akka.Actor.IInternalActorRef actorRef, Akka.Actor.ActorPath path);
Expand Down Expand Up @@ -1274,6 +1281,7 @@ namespace Akka.Actor
public Akka.Actor.IInternalActorRef TempContainer { get; }
public System.Threading.Tasks.Task TerminationTask { get; }
public Akka.Actor.IInternalActorRef ActorOf(Akka.Actor.Internal.ActorSystemImpl system, Akka.Actor.Props props, Akka.Actor.IInternalActorRef supervisor, Akka.Actor.ActorPath path, bool systemService, Akka.Actor.Deploy deploy, bool lookupDeploy, bool async) { }
public Akka.Actor.FutureActorRef<T> CreateFutureRef<T>(System.Threading.Tasks.TaskCompletionSource<T> tcs) { }
public Akka.Actor.Address GetExternalAddressFor(Akka.Actor.Address address) { }
public void Init(Akka.Actor.Internal.ActorSystemImpl system) { }
public void RegisterExtraName(string name, Akka.Actor.IInternalActorRef actor) { }
Expand Down Expand Up @@ -1546,15 +1554,9 @@ namespace Akka.Actor
public void SwapUnderlying(Akka.Actor.ICell cell) { }
protected override void TellInternal(object message, Akka.Actor.IActorRef sender) { }
}
public class RootActorPath : Akka.Actor.ActorPath
public sealed class RootActorPath : Akka.Actor.ActorPath
{
public RootActorPath(Akka.Actor.Address address, string name = "") { }
public override System.Collections.Generic.IReadOnlyList<string> Elements { get; }
public override Akka.Actor.ActorPath Parent { get; }
[Newtonsoft.Json.JsonIgnoreAttribute()]
public override Akka.Actor.ActorPath Root { get; }
public override int CompareTo(Akka.Actor.ActorPath other) { }
public override Akka.Actor.ActorPath WithUid(long uid) { }
}
[Akka.Annotations.InternalApiAttribute()]
public class RootGuardianActorRef : Akka.Actor.LocalActorRef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ namespace Akka.Remote
public System.Threading.Tasks.Task TerminationTask { get; }
public Akka.Remote.RemoteTransport Transport { get; }
public Akka.Actor.IInternalActorRef ActorOf(Akka.Actor.Internal.ActorSystemImpl system, Akka.Actor.Props props, Akka.Actor.IInternalActorRef supervisor, Akka.Actor.ActorPath path, bool systemService, Akka.Actor.Deploy deploy, bool lookupDeploy, bool async) { }
public Akka.Actor.FutureActorRef<T> CreateFutureRef<T>(System.Threading.Tasks.TaskCompletionSource<T> tcs) { }
protected virtual Akka.Actor.IActorRef CreateRemoteDeploymentWatcher(Akka.Actor.Internal.ActorSystemImpl system) { }
protected virtual Akka.Actor.IInternalActorRef CreateRemoteRef(Akka.Actor.ActorPath actorPath, Akka.Actor.Address localAddress) { }
protected virtual Akka.Actor.IInternalActorRef CreateRemoteRef(Akka.Actor.Props props, Akka.Actor.IInternalActorRef supervisor, Akka.Actor.Address localAddress, Akka.Actor.ActorPath rpath, Akka.Actor.Deploy deployment) { }
Expand Down
5 changes: 3 additions & 2 deletions src/core/Akka.Cluster/ClusterDaemon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1561,8 +1561,9 @@ public void StopSeedNodeProcess()
/// Received `Join` message and replies with `Welcome` message, containing
/// current gossip state, including the new joining member.
/// </summary>
/// <param name="node">TBD</param>
/// <param name="roles">TBD</param>
/// <param name="node">The unique address of the joining node.</param>
/// <param name="roles">The roles, if any, of the joining node.</param>
/// <param name="appVersion">The software version of the joining node.</param>
public void Joining(UniqueAddress node, ImmutableHashSet<string> roles, AppVersion appVersion)
{
var selfStatus = LatestGossip.GetMember(SelfUniqueAddress).Status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,22 @@ public void Only_MultiNodeConfig_role_count_used()
private static Dictionary<string, List<NodeTest>> DiscoverSpecs()
{
Environment.SetEnvironmentVariable(MultiNodeFactAttribute.MultiNodeTestEnvironmentName, "1");
using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, new System.Uri(typeof(DiscoveryCases).GetTypeInfo().Assembly.CodeBase).LocalPath))
try
{
using (var discovery = new Discovery())
using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, new System.Uri(typeof(DiscoveryCases).GetTypeInfo().Assembly.CodeBase).LocalPath))
{
controller.Find(false, discovery, TestFrameworkOptions.ForDiscovery());
discovery.Finished.WaitOne();
return discovery.Tests;
using (var discovery = new Discovery())
{
controller.Find(false, discovery, TestFrameworkOptions.ForDiscovery());
discovery.Finished.WaitOne();
return discovery.Tests;
}
}
}
finally
{
Environment.SetEnvironmentVariable(MultiNodeFactAttribute.MultiNodeTestEnvironmentName, null);
}
}

private string KeyFromSpecName(string specName)
Expand Down
Loading

0 comments on commit 193c74e

Please sign in to comment.