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

adding GetChild benchmark #5239

Merged

Conversation

Aaronontheweb
Copy link
Member

Working on cleaning up the read-side resolve pipeline inside Akka.Cluster.Sharding and Akka.Remote. This seemed like a good place to start.

@to11mtm
Copy link
Member

to11mtm commented Aug 31, 2021

How many layers deep do the children get here? Is there a way we can somehow measure difference in perf based on how deep the path is?

@Aaronontheweb
Copy link
Member Author

Data so far:

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 Allocated
ResolveChild 62.07 ns 0.971 ns 0.811 ns -

@Aaronontheweb
Copy link
Member Author

How many layers deep do the children get here? Is there a way we can somehow measure difference in perf based on how deep the path is?

I can add a method to traverse the graph a few layers deeper, yes

@Aaronontheweb
Copy link
Member Author

Ideally, this is the path we want to optimize read-side in Akka.Remote:

internal IInternalActorRef ResolveActorRef(IInternalActorRef actorRef, IReadOnlyCollection<string> pathElements)
{
if (pathElements.Count == 0)
{
_log.Debug("Resolve of empty path sequence fails (per definition)");
return _deadLetters;
}
var child = actorRef.GetChild(pathElements);
if (child.IsNobody())
{
_log.Debug("Resolve of path sequence [/{0}] failed", ActorPath.FormatPathElements(pathElements));
return new EmptyLocalActorRef(_system.Provider, actorRef.Path / pathElements, _eventStream);
}
return (IInternalActorRef)child;
}

It gets called twice per-read and doesn't appear to be cached at all.

@Aaronontheweb
Copy link
Member Author

Ah, I take that back - looks like we do cache inside RARP here:

/// <summary>
        /// Resolves a deserialized path into an <see cref="IActorRef"/>
        /// </summary>
        /// <param name="path">The path of the actor we are attempting to resolve.</param>
        /// <returns>A local <see cref="IActorRef"/> if it exists, <see cref="ActorRefs.Nobody"/> otherwise.</returns>
        public IActorRef ResolveActorRef(string path)
        {
            if (IgnoreActorRef.IsIgnoreRefPath(path))
                return IgnoreRef;

            // using thread local LRU cache, which will call InternalResolveActorRef
            // if the value is not cached
            if (_actorRefResolveThreadLocalCache == null)
            {
                return InternalResolveActorRef(path); // cache not initialized yet
            }
            return _actorRefResolveThreadLocalCache.Cache.GetOrCompute(path);
        }

@Aaronontheweb
Copy link
Member Author

Actually, funnily enough no - that doesn't get used at all inside the AkkaPduCodec

@Aaronontheweb
Copy link
Member Author

Done, expanded the benchmark to include some more scenarios.

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
ResolveChild 64.69 ns 0.145 ns 0.129 ns - -
Resolve3DeepChildRepointableActorRef 652.15 ns 9.237 ns 8.641 ns 0.0839 352 B
Resolve3DeepChildLocalActorRef 311.74 ns 4.924 ns 4.605 ns 0.0629 264 B

@Aaronontheweb Aaronontheweb enabled auto-merge (squash) September 1, 2021 19:30
@Aaronontheweb Aaronontheweb merged commit 682ca13 into akkadotnet:dev Sep 1, 2021
@Aaronontheweb Aaronontheweb deleted the perf/GetChild-performance branch September 1, 2021 19:54
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.

2 participants