Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RemoteActorRefProvider address paring, caching and resolving improvements #5273

Merged
merged 41 commits into from
Oct 1, 2021

Conversation

Zetanova
Copy link
Contributor

@Zetanova Zetanova commented Sep 7, 2021

Small changes to reduce cache entries, memory barriers and unnecessary ActorPath paring

@@ -435,7 +435,7 @@ public Deploy LookUpRemotes(IEnumerable<string> p)

public bool HasAddress(Address address)
{
return address == _local.RootPath.Address || address == RootPath.Address || Transport.Addresses.Any(a => a == address);
return address == _local.RootPath.Address || Transport.Addresses.Contains(address);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see what you meant in your other comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would interest me to make a banchmark on it.

if the volatile fields and the removal of the AddressCache had an impact

@Aaronontheweb
Copy link
Member

@Zetanova I'll benchmark this locally - guess I need to add a guide on how to do that to our CONTRIBUTORS.md file

@Zetanova
Copy link
Contributor Author

Zetanova commented Sep 8, 2021

Yes, would be nice, that benchmark could be executed with a one line command.

Maybe hosting benchmark server to track and post automatically progress over time.
On every commit to dev and on a request from a moderator on a PR.

If there is a perf issue, it would be then visible.

@Aaronontheweb
Copy link
Member

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  Job-JZZTLK : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

InvocationCount=1  UnrollFactor=1  
Method StateMode MsgCount Mean Error StdDev
SingleRequestResponseToLocalEntity Persistence 10000 112.105 ms 2.1509 ms 3.7672 ms
StreamingToLocalEntity Persistence 10000 5.797 ms 0.4959 ms 1.4228 ms
SingleRequestResponseToRemoteEntity Persistence 10000 3,862.783 ms 17.1057 ms 16.0006 ms
SingleRequestResponseToRemoteEntityWithLocalProxy Persistence 10000 4,190.948 ms 22.1583 ms 19.6428 ms
StreamingToRemoteEntity Persistence 10000 444.646 ms 4.0662 ms 3.3954 ms
SingleRequestResponseToLocalEntity DData 10000 112.130 ms 2.2021 ms 4.4984 ms
StreamingToLocalEntity DData 10000 4.640 ms 0.2222 ms 0.6516 ms
SingleRequestResponseToRemoteEntity DData 10000 NA NA NA
SingleRequestResponseToRemoteEntityWithLocalProxy DData 10000 4,227.038 ms 7.5135 ms 6.2741 ms
StreamingToRemoteEntity DData 10000 443.275 ms 6.2937 ms 5.2555 ms

Benchmarks with issues:
ShardMessageRoutingBenchmarks.SingleRequestResponseToRemoteEntity: Job-JZZTLK(InvocationCount=1, UnrollFactor=1) [StateMode=DData, MsgCount=10000]

@Aaronontheweb
Copy link
Member

D:\Repositories\olympus\akka.net\src\benchmark\Akka.Cluster.Benchmarks [perf-remote-actorref-provider ≡ +1 ~0 -0 !]
λ  dotnet run -c Release --framework netcoreapp3.1 --filter **Routing**

To run that, FYI

@Zetanova
Copy link
Contributor Author

Zetanova commented Sep 8, 2021

Looks better or only sometimes a racy startup ?

@Aaronontheweb
Copy link
Member

The numbers on RemotePingPong look slightly better on this PR: avergaging 252k vs 249k on my system.

The Akka.Cluster.Sharding benchmark is more aggressive - doesn't benefit from happy path optimizations like caching and I/O batching.

@Zetanova
Copy link
Contributor Author

Zetanova commented Sep 8, 2021

thx, 1% is good for it.

I will try to find the current bottleneck

@Aaronontheweb
Copy link
Member

thx, 1% is good for it.

I will try to find the current bottleneck

Yes it is - and it's a consistent improvement.

@Zetanova
Copy link
Contributor Author

@Aaronontheweb I found a very dirty class and cleaned it up ... the ActorPath
It should result in better perf and mem footprint

One other thing that I discovered is that the whole ActorPath Elements are more or less never getting reused.
If a remote inbound ActorPath is parsed, it will create every single child-element for it.

Following example of inbound paths

akka.tcp://remotesystem@localhost:8080/user/a1/b1
akka.tcp://remotesystem@localhost:8080/user/a1/b2
akka.tcp://remotesystem@localhost:8080/user/a1/b2/c1

would result in following instances:
3x ActorPath Cache Entries
3x Address instances
3x RootActorPath instances
3x ChildActorPath: /user
3x ChildActorPath: /user/a1
1x ChildActorPath: /user/a1/b1
2x ChildActorPath: /user/a1/b2
1x ChildActorPath: /user/a1/b2/c1

Total: ~19 instances
Optimal would be ~10 instances

they are not big objects, but the multiplier is a bit worried

@Aaronontheweb
Copy link
Member

Haven't reviewed the code yet but this looks promising!

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,    141844,    1410.20
         5, 1000000,    266809,    3748.34
        10, 2000000,    269252,    7428.20
        15, 3000000,    268097,   11190.80
        20, 4000000,    264009,   15151.94
        25, 5000000,    264887,   18876.53
        30, 6000000,    264411,   22692.65

That's a 20k msg/s improvement over what we published in v1.4.25 https://github.com/akkadotnet/akka.net/releases/tag/1.4.25

Need to approve the API changes here so the full test suite can run though, in case there's correctness issues. But so far so good!

@Aaronontheweb
Copy link
Member

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  Job-ZSODNY : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

InvocationCount=1  UnrollFactor=1  
Method StateMode MsgCount Mean Error StdDev
SingleRequestResponseToLocalEntity Persistence 10000 111.257 ms 2.2108 ms 3.0993 ms
StreamingToLocalEntity Persistence 10000 5.841 ms 0.4845 ms 1.4132 ms
SingleRequestResponseToRemoteEntity Persistence 10000 3,832.930 ms 24.3505 ms 22.7775 ms
SingleRequestResponseToRemoteEntityWithLocalProxy Persistence 10000 4,226.208 ms 45.1683 ms 53.7696 ms
StreamingToRemoteEntity Persistence 10000 436.881 ms 6.2386 ms 5.5304 ms
SingleRequestResponseToLocalEntity DData 10000 109.177 ms 2.1479 ms 2.5569 ms
StreamingToLocalEntity DData 10000 4.850 ms 0.2574 ms 0.7303 ms
SingleRequestResponseToRemoteEntity DData 10000 4,176.422 ms 80.2593 ms 98.5657 ms
SingleRequestResponseToRemoteEntityWithLocalProxy DData 10000 4,334.926 ms 16.0158 ms 14.1976 ms
StreamingToRemoteEntity DData 10000 459.933 ms 7.5976 ms 7.1068 ms

@Zetanova
Copy link
Contributor Author

It is not finished.

I only suspect that the instance count of ActorPaths have a bad effect
and deduplication would resolve it.

Following things need to be discussed and/or decided:

The RootActorPath and ChildActorPath classes are now empty,
at this point in time they could be removed and only AcotrPath itself used.
This would increase perf a small bit (no type casting and no virtcalls).
OR
RootActorPath could be used to hold shared instances like address, cache etc.
This could be used to deduplicate instances on parsing.
It would not really reduce the perf more, but would reduce the memory pressure.
OR
We introduce some kind of context object for parsing
The ActorRefProviders would hold an instance and use it for parsing.

The deduplication itself has its own problems,
to find a parent ActorPath instance from a child path at parsing time
has its own problems. If a remote only receives following two paths:

akka.tcp://remotesystem@localhost:8080/user/a1/b2/c1
akka.tcp://remotesystem@localhost:8080/user/a1/b2/c2

To find/deduplicate the instance for Address and RootActorPath is easy
but not for the ChildActorPaths /a1/b2 and /a1

Copy link
Member

@to11mtm to11mtm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks promising. A couple of minor suggestions here.

Comment on lines 216 to 227
if (_depth == 0)
return ImmutableArray<string>.Empty;

var b = ImmutableArray.CreateBuilder<string>(_depth);
b.Count = _depth;
var p = this;
for (var i = 0; i < _depth; i++)
{
b[_depth - i - 1] = p.Name;
p = p._parent;
}
return b.ToImmutable();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, what about...

                if (_depth == 0)
                    return ImmutableArray<string>.Empty; //Still use this because it saves alloc.

                var b = new List<string>(_depth);
                var p = this;
                for (var i = 0; i < _depth; i++)
                {
                    b.Add(p.Name);
                    p = p._parent;
                }
                b.Reverse();
                return b;

This will save us the array alloc on .ToImmutable() and allocation of builder. (Not counting the copy since Reverse is a non-alloc copy).

If you'd prefer to stick with ImmutableArray, consider .MoveToImmutable() instead of .ToImmutable() , MoveTo will pull the array out without allocating a new one and copying the contents (You'll still pay the small cost of allocating the Builder of course,) and is the one to use if you are not re-using the builder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is what I intended to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use List<> to return a IReadOnlyList<>
Before there was an up cast to List<> in the code and this should never be,
ImmutableArray is very performant and protects against "upcasts" and changes.

Comment on lines 247 to 254
b.Count = _depth;
var p = this;
for (var i = 0; i < _depth; i++)
{
b[_depth - i - 1] = i > 0 ? p._name : AppendUidFragment(p._name);
p = p._parent;
}
return b.ToImmutable();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comments about .ToImmutable() vs List or MoveToImmutable().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is what I intended to do.


p.Name.CopyTo(0, buffer, offset + 1, p.Name.Length);
// Concatenate segments (in reverse order) into buffer with '/' prefixes
Span<char> buffer = stackalloc char[totalLength];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still worry here whether a path can be long enough that we should -not- be allocating on the stack.

This is a bigger concern on MacOS where Stack sizes can be small.

Consider:

Span<char> buffer = totalLength <256 ? stackalloc char[totalLength] : new char[totalLength]; // pick a good number here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sry, completely forgot, 1024 is a good number
I will fix it and make a unit test for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows 10MB stackallock is no issue.
The stackallock could be removed, when we have String.Create()

@Aaronontheweb
Copy link
Member

ActorPathBenchmarks

This PR

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  DefaultJob : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

Method Mean Error StdDev Gen 0 Allocated
ActorPath_Parse 281.162 ns 2.0975 ns 1.8594 ns 0.1106 464 B
ActorPath_Concat 53.146 ns 0.3640 ns 0.3227 ns 0.0268 112 B
ActorPath_Equals 5.400 ns 0.0577 ns 0.0511 ns - -
ActorPath_ToString 57.856 ns 0.4927 ns 0.4608 ns 0.0267 112 B
ActorPath_ToSerializationFormat 62.798 ns 0.4608 ns 0.4310 ns 0.0267 112 B
ActorPath_ToSerializationFormatWithAddress 64.607 ns 0.5678 ns 0.5311 ns 0.0267 112 B

dev

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  DefaultJob : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

Method Mean Error StdDev Gen 0 Allocated
ActorPath_Parse 475.89 ns 5.596 ns 5.234 ns 0.1068 448 B
ActorPath_Concat 51.82 ns 0.546 ns 0.456 ns 0.0268 112 B
ActorPath_Equals 19.00 ns 0.047 ns 0.042 ns - -
ActorPath_ToString 195.94 ns 2.064 ns 1.930 ns 0.0515 216 B
ActorPath_ToSerializationFormat 221.73 ns 0.824 ns 0.771 ns 0.0515 216 B
ActorPath_ToSerializationFormatWithAddress 232.70 ns 2.254 ns 2.108 ns 0.0515 216 B

Allocations up a tiny amount on ActorPath.Parse, but cut in half everywhere else. ActorPath.Parse speed improved by (eyeballing it) 40-45%. Big difference!

LruBoundedCacheBenchmarks

This PR

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  Job-CVYXVJ : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

InvocationCount=10000000  
Method Mean Error StdDev Allocated
ActorPathCacheHitBenchmark 64.48 ns 0.075 ns 0.058 ns -
ActorPathCacheMissBenchmark 69.18 ns 0.135 ns 0.119 ns -

dev

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  Job-DJGDWL : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

InvocationCount=10000000  
Method Mean Error StdDev Allocated
ActorPathCacheHitBenchmark 58.17 ns 0.166 ns 0.155 ns -
ActorPathCacheMissBenchmark 72.51 ns 0.524 ns 0.409 ns -

LRU Cache metrics are a bit of a wash by the looks of it.

@Aaronontheweb
Copy link
Member

Akka.Cluster.Sharding benchmarks seem about the same

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19041.1165 (2004/May2020Update/20H1)
AMD Ryzen 7 1700, 1 CPU, 16 logical and 8 physical cores
.NET SDK=5.0.302
  [Host]     : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT
  Job-IQESDM : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT

InvocationCount=1  UnrollFactor=1  
Method StateMode MsgCount Mean Error StdDev
SingleRequestResponseToLocalEntity Persistence 10000 114.220 ms 2.2654 ms 4.5763 ms
StreamingToLocalEntity Persistence 10000 5.556 ms 0.4369 ms 1.2677 ms
SingleRequestResponseToRemoteEntity Persistence 10000 3,796.920 ms 33.2036 ms 31.0587 ms
SingleRequestResponseToRemoteEntityWithLocalProxy Persistence 10000 NA NA NA
StreamingToRemoteEntity Persistence 10000 415.103 ms 4.7774 ms 4.4687 ms
SingleRequestResponseToLocalEntity DData 10000 110.511 ms 1.8125 ms 2.2259 ms
StreamingToLocalEntity DData 10000 5.005 ms 0.3023 ms 0.8625 ms
SingleRequestResponseToRemoteEntity DData 10000 3,800.727 ms 27.9457 ms 26.1404 ms
SingleRequestResponseToRemoteEntityWithLocalProxy DData 10000 4,282.207 ms 15.4803 ms 13.7229 ms
StreamingToRemoteEntity DData 10000 418.884 ms 3.8452 ms 3.5968 ms

Benchmarks with issues:
ShardMessageRoutingBenchmarks.SingleRequestResponseToRemoteEntityWithLocalProxy: Job-IQESDM(InvocationCount=1, UnrollFactor=1) [StateMode=Persistence, MsgCount=10000]

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good but have some questions and some minor changes so far

src/core/Akka.Remote/RemoteActorRefProvider.cs Outdated Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/Address.cs Show resolved Hide resolved
Copy link
Contributor Author

@Zetanova Zetanova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will make the view changes and look/test for Root parsing
akka://sysName/ should be equal to akka://sysName and
TryParse(rootPath, "/", out var _)

src/core/Akka.Remote/Serialization/ActorPathCache.cs Outdated Show resolved Hide resolved
@@ -178,14 +178,14 @@ public static Task<T> Ask<T>(this ICanTell self, Func<IActorRef, object> message
/// <returns>Provider used for Ask pattern implementation</returns>
internal static IActorRefProvider ResolveProvider(ICanTell self)
{
if (self is ActorSelection)
return ResolveProvider(self.AsInstanceOf<ActorSelection>().Anchor);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use native c# tools and seal classes.
To seal a class will improve ìs, as and switch pattern matching

src/core/Akka.Remote/Serialization/ActorPathCache.cs Outdated Show resolved Hide resolved
src/core/Akka.Remote/Serialization/ActorPathCache.cs Outdated Show resolved Hide resolved
src/core/Akka.Remote/Serialization/LruBoundedCache.cs Outdated Show resolved Hide resolved
@@ -117,7 +150,7 @@ public CacheStatistics(int entries, int maxProbeDistance, double averageProbeDis
/// <typeparam name="TValue">The type of value used in the cache.</typeparam>
internal abstract class LruBoundedCache<TKey, TValue> where TValue : class
{
protected LruBoundedCache(int capacity, int evictAgeThreshold)
protected LruBoundedCache(int capacity, int evictAgeThreshold, IEqualityComparer<TKey> keyComparer)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key was not tested for null and the caller can give something like StringComparer.OriginalIgnoreCase

I am trying to remove the "Compute" from the cache without rehashing and to pass a func<> as arg

the best pattern for caching is

if(!cache.TryGet(key, out var value))
{
     value = new object();
     cache.Set(key, value);
}

we could try to make (in an other PR)

if(!cache.TryGet(key, out var value, out var entry))
{
     value = new object();
     cache.Set(entry, value); //or entry.Set(Value);
}

The compute should be at the user/caller not inside the cache itself.
Sometimes the caller just has more information and can make better decisions


protected AkkaPduCodec(ActorSystem system)
{
System = system;
AddressCache = AddressThreadLocalCache.For(system);
ActorPathCache = ActorPathThreadLocalCache.For(system);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, AddressCache is now dark

The AkkaPduCodec (better the EndPointReader) is the best place to directly instanced the ActorPathCache and use it.
When then ActorPathCache is freed from ThreadLocal and bound to an Endpoint then it would produce the best cache-hits.

The only thing what needs an API change, would be the provider.ResolveActorRefWithLocalAddress(envelopeContainer.Recipient.Path, localAddress) call.
this needs to be extended or replaced with an Context parameter.
Something like ResolveContext with LocalAddress and the ActorPathCache

src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/Address.cs Show resolved Hide resolved
@Zetanova
Copy link
Contributor Author

The ActorPathBenchmarks has memory increase because the ActorPath class increased by the field int _depth
The ActorPathCache makes now more, it does also do a lookup for the root

@Aaronontheweb
Copy link
Member

The ActorPathBenchmarks has memory increase because the ActorPath class increased by the field int _depth

That's fine - the results are worth the trade-off.

@Zetanova
Copy link
Contributor Author

Why Akka.Persistence.TCK.Tests.MemorySnapshotStoreSpec.MemorySnapshotStore_is_threadsafe [FAIL] failed of a sudden?

Is this a startup issue again?
This is the next thing I want to improve.

@Aaronontheweb
Copy link
Member

Why Akka.Persistence.TCK.Tests.MemorySnapshotStoreSpec.MemorySnapshotStore_is_threadsafe [FAIL] failed of a sudden?

Is this a startup issue again? This is the next thing I want to improve.

It's probably a racy spec - I fixed a ton of these last month but there's always more...

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/ActorPath.cs Show resolved Hide resolved
src/core/Akka/Actor/Address.cs Show resolved Hide resolved
@Aaronontheweb Aaronontheweb changed the title [WIP] RemoteActorRefProvider address paring, caching and resolving improvments RemoteActorRefProvider address paring, caching and resolving improvments Oct 1, 2021
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) October 1, 2021 14:45
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) October 1, 2021 14:46
@Aaronontheweb
Copy link
Member

Aaronontheweb commented Oct 1, 2021

Nice work @Zetanova - going to merge this into v1.4.27

@Aaronontheweb Aaronontheweb added this to the 1.4.27 milestone Oct 1, 2021
@Aaronontheweb Aaronontheweb merged commit 01c35a9 into akkadotnet:dev Oct 1, 2021
@Zetanova Zetanova deleted the perf-remote-actorref-provider branch October 2, 2021 08:28
@Aaronontheweb Aaronontheweb changed the title RemoteActorRefProvider address paring, caching and resolving improvments RemoteActorRefProvider address paring, caching and resolving improvements Oct 11, 2021
This was referenced Oct 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants