Skip to content

Commit a8347c5

Browse files
Merge pull request #5096 from akkadotnet/dev
v1.4.21 Release
2 parents 758590f + 5c9f8a7 commit a8347c5

File tree

103 files changed

+2993
-1165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+2993
-1165
lines changed

ISSUE_TEMPLATE.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

RELEASE_NOTES.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,93 @@
1+
#### 1.4.21 June 16 2021 ####
2+
**Maintenance Release for Akka.NET 1.4**
3+
4+
Akka.NET v1.4.21 is a significant release that includes major performance improvements, bug fixes, and a major update to the [Akka.DependencyInjection NuGet package](https://getakka.net/articles/actors/dependency-injection.html).
5+
6+
**Performance Improvements**
7+
Akka.NET v1.4.21 includes some major performance fixes and improvements:
8+
9+
* [`Ask` is now ~10% faster](https://github.com/akkadotnet/akka.net/pull/5051)
10+
* [`MurmurHash` is 33% faster and allocates 0 memory](https://github.com/akkadotnet/akka.net/pull/5028) - used _heavily_ in DData, Cluster Sharding, and Consistent Hash Routers
11+
* `ActorPath.Parse` went from 1672 ns/op to 527 ns/op - a 68% improvement in throughput and a 50% reduction in memory. See [#5039](https://github.com/akkadotnet/akka.net/pull/5039) and [#5068](https://github.com/akkadotnet/akka.net/pull/5068).
12+
* [Akka.Remote: remove `ActorPath.ToString` call from `ResolveActorRefWithLocalAddress`](https://github.com/akkadotnet/akka.net/pull/5034)
13+
* **Important**: [Revert `ThreadPool.SetMinThreads(0,0)`](https://github.com/akkadotnet/akka.net/pull/5059) - based on the input from users on "[Akka.NET v1.4.19: ChannelExecutor performance data](https://github.com/akkadotnet/akka.net/discussions/4983)"
14+
15+
Our observed performance numbers for Akka.Remote show a significant increase in performance for v1.4.21 over v1.4.20:
16+
17+
*Before*
18+
19+
```
20+
PS> dotnet run -c Release --framework netcoreapp3.1
21+
OSVersion: Microsoft Windows NT 6.2.9200.0
22+
ProcessorCount: 16
23+
ClockSpeed: 0 MHZ
24+
Actor Count: 32
25+
Messages sent/received per client: 200000 (2e5)
26+
Is Server GC: True
27+
Thread count: 109
28+
29+
Num clients, Total [msg], Msgs/sec, Total [ms]
30+
1, 200000, 113379, 1764.56
31+
5, 1000000, 186429, 5364.05
32+
10, 2000000, 185340, 10791.11
33+
15, 3000000, 183218, 16374.06
34+
20, 4000000, 179824, 22244.63
35+
25, 5000000, 182716, 27365.89
36+
30, 6000000, 182039, 32960.61
37+
```
38+
39+
*After*
40+
41+
```
42+
PS> dotnet run -c Release --framework netcoreapp3.1
43+
OSVersion: Microsoft Windows NT 6.2.9200.0
44+
ProcessorCount: 16
45+
ClockSpeed: 0 MHZ
46+
Actor Count: 32
47+
Messages sent/received per client: 200000 (2e5)
48+
Is Server GC: True
49+
Thread count: 111
50+
51+
Num clients, Total [msg], Msgs/sec, Total [ms]
52+
1, 200000, 109770, 1822.14
53+
5, 1000000, 192902, 5184.79
54+
10, 2000000, 191663, 10435.53
55+
15, 3000000, 191339, 15679.11
56+
20, 4000000, 192725, 20755.78
57+
25, 5000000, 189754, 26350.14
58+
30, 6000000, 189772, 31617.20
59+
```
60+
61+
> N.B. these after numbers don't benefit from the performance benefits we observed in v1.4.20 when we invoked `ThreadPool.SetMinThreads(0,0)`, which makes them even more impressive.
62+
63+
**Akka.DependencyInjection Updates**
64+
We had one major issue we implemented in v1.4.21 for Akka.DependencyInjection: [Abstraction of `ServiceProvider`, Improving Akka.DependencyInjection ](https://github.com/akkadotnet/akka.net/pull/4814)
65+
66+
What this change did was:
67+
68+
* Deprecate the `Akka.DependencyInjection.ServiceProvider` class in favor of the `Akka.DependencyInjection.DependencyResolver` class - to avoid namespace collision with Microsoft.Extensions.DependencyInjection.ServiceProvider;
69+
* Deprecates the `Akka.DependencyInjection.ServiceProviderSetup` class in favor of the `Akka.DependencyInjection.DependencyResolverSetup` class for consistency reasons;
70+
* `Akka.DependencyInjection.DependencyResolver` now takes an input of type [`IDependencyResolver`](https://getakka.net/api/Akka.DependencyInjection.IDependencyResolver.html), which allows users to abstract away the `IServiceProvider` and mock / replace it during unit testing; and
71+
* Added some non-generic `Props` methods for dynamically spawning actors via DI.
72+
73+
All of these changes are backwards-compatible with v1.4.20 and earlier - and the deprecation warnings will appear in your code when you upgrade. If you run into any [issues upgrading to Akka.DependencyInjection v1.4.21 please reply on this thread](https://github.com/akkadotnet/akka.net/discussions/5070)!
74+
75+
**Other Changes and Fixes**
76+
77+
* [Akka.Streams: A couple of fixes affecting the `FileSubscriber`](https://github.com/akkadotnet/akka.net/pull/5035)
78+
* [Akka.DistributedData: memory leak when recovering events from LMDB data store](https://github.com/akkadotnet/akka.net/issues/5022)
79+
* [Akka.DistributedData: port `VectorClock` performance optimizations to `VersionVector` and similar types](https://github.com/akkadotnet/akka.net/issues/4956)
80+
81+
To see the [full set of fixes in Akka.NET v1.4.21, please see the milestone on Github](https://github.com/akkadotnet/akka.net/milestone/51).
82+
83+
| COMMITS | LOC+ | LOC- | AUTHOR |
84+
| --- | --- | --- | --- |
85+
| 5 | 34 | 24 | Aaron Stannard |
86+
| 4 | 196 | 77 | Gregorius Soedharmo |
87+
| 3 | 3 | 3 | dependabot[bot] |
88+
| 1 | 2 | 2 | Wessel Kranenborg |
89+
| 1 | 1 | 1 | Martijn Schoemaker |
90+
191
#### 1.4.20 May 12 2021 ####
292
**Maintenance Release for Akka.NET 1.4**
393

docs/articles/actors/dispatchers.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ In Akka.NET v1.4.19 we will be introducing an opt-in feature, the `ChannelExecut
171171

172172
During its initial development and benchmarks, we observed the following:
173173

174-
1. The `ChannelExecutor` tremendously reduced idle CPU and max busy CPU even during peak message throughput, primarily as a result of dynamically shrinking the total `ThreadPool` to only the necessary size. This resolves one of the largest complaints large users of Akka.NET have today. However, **in order for this setting to be effective `ThreadPool.SetMin(0,0)` must also be set**. We are considering doing this inside the `ActorSystem.Create` method, those settings don't work for you you can easily override them by simply calling `ThreadPool.SetMin(yourValue, yourValue)` again after `ActorSystem.Create` has exited.
174+
1. The `ChannelExecutor` tremendously reduced idle CPU and max busy CPU even during peak message throughput, primarily as a result of dynamically shrinking the total `ThreadPool` to only the necessary size. This resolves one of the largest complaints large users of Akka.NET have today.
175175
2. The `ChannelExecutor` actually beat the `ForkJoinDispatcher` and others on performance even in environments like Docker and bare metal on Windows.
176176

177177
> [!NOTE]
@@ -220,9 +220,6 @@ akka.remote.backoff-remote-dispatcher {
220220

221221
This will enable the `ChannelExecutor` to run everywhere and all Akka.NET loads, with the exception of anything you manually allocate onto a `ForkJoinDispatcher` or `PinnedDispatcher`, will be managed by the `ThreadPool`.
222222

223-
> [!IMPORTANT]
224-
> As of Akka.NET v1.4.19, we call `ThreadPool.SetMinThreads(0,0)` inside the `ActorSystem.Create` method as we've found that the default `ThreadPool` minimum values have a negative impact on performance. However, if this causes undesireable side effects for you inside your application you can always override those settings by calling `ThreadPool.SetMinThreads(yourValue, yourValue)` again after you've created your `ActorSystem`.
225-
226223
#### Common Dispatcher Configuration
227224

228225
The following configuration keys are available for any dispatcher configuration:

docs/articles/actors/receive-actor-api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,10 @@ For more information on Tasks, check out the [MSDN documentation](https://msdn.m
405405
> When using task callbacks inside actors, you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time.
406406
407407
### Forward message
408-
You can forward a message from one actor to another. This means that the original sender address/reference is maintained even though the message is going through a 'mediator'. This can be useful when writing actors that work as routers, load-balancers, replicators etc. You need to pass along your context variable as well.
408+
You can forward a message from one actor to another. This means that the original sender address/reference is maintained even though the message is going through a 'mediator'. This can be useful when writing actors that work as routers, load-balancers, replicators etc.
409409

410410
```csharp
411-
target.Forward(result, Context);
411+
target.Forward(result);
412412
```
413413

414414
## Receive messages

src/Akka.sln

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DependencyInjection.Te
240240
EndProject
241241
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AspNetCore", "AspNetCore", "{162F5991-EA57-4221-9B70-F9B6FEC18036}"
242242
EndProject
243-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Akka.AspNetCore", "examples\AspNetCore\Samples.Akka.AspNetCore\Samples.Akka.AspNetCore.csproj", "{D62F4AD6-318F-4ECC-B875-83FA9933A81B}"
243+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Akka.AspNetCore", "examples\AspNetCore\Samples.Akka.AspNetCore\Samples.Akka.AspNetCore.csproj", "{D62F4AD6-318F-4ECC-B875-83FA9933A81B}"
244244
EndProject
245-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerializationBenchmarks", "benchmark\SerializationBenchmarks\SerializationBenchmarks.csproj", "{2E4B9584-42CC-4D17-B719-9F462B16C94D}"
245+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerializationBenchmarks", "benchmark\SerializationBenchmarks\SerializationBenchmarks.csproj", "{2E4B9584-42CC-4D17-B719-9F462B16C94D}"
246+
EndProject
247+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DDataStressTest", "examples\Cluster\DData\DDataStressTest\DDataStressTest.csproj", "{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}"
246248
EndProject
247249
Global
248250
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1123,6 +1125,18 @@ Global
11231125
{2E4B9584-42CC-4D17-B719-9F462B16C94D}.Release|x64.Build.0 = Release|Any CPU
11241126
{2E4B9584-42CC-4D17-B719-9F462B16C94D}.Release|x86.ActiveCfg = Release|Any CPU
11251127
{2E4B9584-42CC-4D17-B719-9F462B16C94D}.Release|x86.Build.0 = Release|Any CPU
1128+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1129+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|Any CPU.Build.0 = Debug|Any CPU
1130+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|x64.ActiveCfg = Debug|Any CPU
1131+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|x64.Build.0 = Debug|Any CPU
1132+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|x86.ActiveCfg = Debug|Any CPU
1133+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Debug|x86.Build.0 = Debug|Any CPU
1134+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|Any CPU.ActiveCfg = Release|Any CPU
1135+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|Any CPU.Build.0 = Release|Any CPU
1136+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|x64.ActiveCfg = Release|Any CPU
1137+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|x64.Build.0 = Release|Any CPU
1138+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|x86.ActiveCfg = Release|Any CPU
1139+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}.Release|x86.Build.0 = Release|Any CPU
11261140
EndGlobalSection
11271141
GlobalSection(SolutionProperties) = preSolution
11281142
HideSolutionNode = FALSE
@@ -1230,6 +1244,7 @@ Global
12301244
{162F5991-EA57-4221-9B70-F9B6FEC18036} = {D3AF8295-AEB5-4324-AA82-FCC0014AC310}
12311245
{D62F4AD6-318F-4ECC-B875-83FA9933A81B} = {162F5991-EA57-4221-9B70-F9B6FEC18036}
12321246
{2E4B9584-42CC-4D17-B719-9F462B16C94D} = {73108242-625A-4D7B-AA09-63375DBAE464}
1247+
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50} = {C50E1A9E-820C-4E75-AE39-6F96A99AC4A7}
12331248
EndGlobalSection
12341249
GlobalSection(ExtensibilityGlobals) = postSolution
12351250
SolutionGuid = {03AD8E21-7507-4E68-A4E9-F4A7E7273164}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="ActorMemoryFootprintBenchmarks.cs" company="Akka.NET Project">
3+
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
4+
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
5+
// </copyright>
6+
//-----------------------------------------------------------------------
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Text;
11+
using System.Threading.Tasks;
12+
using Akka.Actor;
13+
using Akka.Benchmarks.Configurations;
14+
using BenchmarkDotNet.Attributes;
15+
using BenchmarkDotNet.Engines;
16+
17+
namespace Akka.Benchmarks.Actor
18+
{
19+
[Config(typeof(MicroBenchmarkConfig))]
20+
[SimpleJob(RunStrategy.Monitoring, targetCount: 25, warmupCount: 5)]
21+
public class ActorMemoryFootprintBenchmark
22+
{
23+
public ActorSystem Sys;
24+
public Props Props;
25+
26+
[Params(10_000)]
27+
public int SpawnCount { get; set; }
28+
29+
[GlobalSetup]
30+
public void Setup()
31+
{
32+
Sys = ActorSystem.Create("Bench");
33+
Props = Props.Create(() => new TempActor());
34+
}
35+
36+
private class TempActor : UntypedActor
37+
{
38+
protected override void OnReceive(object message)
39+
{
40+
41+
}
42+
}
43+
44+
[Benchmark]
45+
public void SpawnActor()
46+
{
47+
for(var i = 0; i < SpawnCount; i++)
48+
Sys.ActorOf(Props);
49+
}
50+
51+
[GlobalCleanup]
52+
public async Task Cleanup()
53+
{
54+
await Sys.Terminate();
55+
}
56+
}
57+
}

src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ public class ActorPathBenchmarks
1616
{
1717
private ActorPath x;
1818
private ActorPath y;
19+
private ActorPath _childPath;
20+
private Address _sysAdr = new Address("akka.tcp", "system", "127.0.0.1", 1337);
21+
private Address _otherAdr = new Address("akka.tcp", "system", "127.0.0.1", 1338);
1922

2023
[GlobalSetup]
2124
public void Setup()
2225
{
23-
x = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "user");
24-
y = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "system");
26+
x = new RootActorPath(_sysAdr, "user");
27+
y = new RootActorPath(_sysAdr, "system");
28+
_childPath = x / "parent" / "child";
2529
}
2630

2731
[Benchmark]
@@ -45,7 +49,19 @@ public bool ActorPath_Equals()
4549
[Benchmark]
4650
public string ActorPath_ToString()
4751
{
48-
return x.ToString();
52+
return _childPath.ToString();
53+
}
54+
55+
[Benchmark]
56+
public string ActorPath_ToSerializationFormat()
57+
{
58+
return _childPath.ToSerializationFormat();
59+
}
60+
61+
[Benchmark]
62+
public string ActorPath_ToSerializationFormatWithAddress()
63+
{
64+
return _childPath.ToSerializationFormatWithAddress(_otherAdr);
4965
}
5066
}
5167
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="NameAndUidBenchmarks.cs" company="Akka.NET Project">
3+
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
4+
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
5+
// </copyright>
6+
//-----------------------------------------------------------------------
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Text;
11+
using Akka.Actor;
12+
using Akka.Benchmarks.Configurations;
13+
using BenchmarkDotNet.Attributes;
14+
15+
namespace Akka.Benchmarks.Actor
16+
{
17+
[Config(typeof(MicroBenchmarkConfig))]
18+
public class NameAndUidBenchmarks
19+
{
20+
public const string ActorPath = "foo#11241311";
21+
22+
[Benchmark]
23+
public NameAndUid ActorCell_SplitNameAndUid()
24+
{
25+
return ActorCell.SplitNameAndUid(ActorPath);
26+
}
27+
28+
[Benchmark]
29+
public (string name, int uid) ActorCell_GetNameAndUid()
30+
{
31+
return ActorCell.GetNameAndUid(ActorPath);
32+
}
33+
}
34+
}

src/benchmark/Akka.Benchmarks/Akka.Benchmarks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
10+
<PackageReference Include="BenchmarkDotNet" Version="0.13.0" />
1111
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
1212
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
1313
<!-- FluentAssertions is used in some benchmarks to validate internal behaviors -->

0 commit comments

Comments
 (0)