Skip to content

Commit

Permalink
Remove Uri.TryParse and replace with Span<char> parsing (#5039)
Browse files Browse the repository at this point in the history
* `Span<char>`-ifying ActorPath and Address parsing

Abstraction of ServiceProvider, Improving Akka.DependencyInjection (#4814)

* Abstraction of ServiceProvider

* introduced non-breaking Akka.DependencyInjection API changes

* fixed unit tests / Props bug

* fixed up DelegateInjectionSpecs

* Added type checking for `Props(Type type, params object[] args)`

* fixed non-generic `Props()` method

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

completed work on ActorPath parsing

* restore Parse performance to ActorPath.Parse

* fixed `ActorPath.ToString()`
  • Loading branch information
Aaronontheweb committed May 28, 2021
1 parent 98ef574 commit c21289e
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 71 deletions.
22 changes: 19 additions & 3 deletions src/benchmark/Akka.Benchmarks/Actor/ActorPathBenchmarks.cs
Expand Up @@ -16,12 +16,16 @@ public class ActorPathBenchmarks
{
private ActorPath x;
private ActorPath y;
private ActorPath _childPath;
private Address _sysAdr = new Address("akka.tcp", "system", "127.0.0.1", 1337);
private Address _otherAdr = new Address("akka.tcp", "system", "127.0.0.1", 1338);

[GlobalSetup]
public void Setup()
{
x = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "user");
y = new RootActorPath(new Address("akka.tcp", "system", "127.0.0.1", 1337), "system");
x = new RootActorPath(_sysAdr, "user");
y = new RootActorPath(_sysAdr, "system");
_childPath = x / "parent" / "child";
}

[Benchmark]
Expand All @@ -45,7 +49,19 @@ public bool ActorPath_Equals()
[Benchmark]
public string ActorPath_ToString()
{
return x.ToString();
return _childPath.ToString();
}

[Benchmark]
public string ActorPath_ToSerializationFormat()
{
return _childPath.ToSerializationFormat();
}

[Benchmark]
public string ActorPath_ToSerializationFormatWithAddress()
{
return _childPath.ToSerializationFormatWithAddress(_otherAdr);
}
}
}
34 changes: 34 additions & 0 deletions src/benchmark/Akka.Benchmarks/Actor/NameAndUidBenchmarks.cs
@@ -0,0 +1,34 @@
//-----------------------------------------------------------------------
// <copyright file="NameAndUidBenchmarks.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using Akka.Actor;
using Akka.Benchmarks.Configurations;
using BenchmarkDotNet.Attributes;

namespace Akka.Benchmarks.Actor
{
[Config(typeof(MicroBenchmarkConfig))]
public class NameAndUidBenchmarks
{
public const string ActorPath = "foo#11241311";

[Benchmark]
public NameAndUid ActorCell_SplitNameAndUid()
{
return ActorCell.SplitNameAndUid(ActorPath);
}

[Benchmark]
public (string name, int uid) ActorCell_GetNameAndUid()
{
return ActorCell.GetNameAndUid(ActorPath);
}
}
}
2 changes: 2 additions & 0 deletions src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
Expand Up @@ -115,6 +115,7 @@ namespace Akka.Actor
protected bool SetChildrenTerminationReason(Akka.Actor.Internal.SuspendReason reason) { }
public void SetReceiveTimeout(System.Nullable<System.TimeSpan> timeout = null) { }
protected void SetTerminated() { }
[System.ObsoleteAttribute("Not used. Will be removed in Akka.NET v1.5.")]
public static Akka.Actor.NameAndUid SplitNameAndUid(string name) { }
public virtual void Start() { }
protected void Stash(Akka.Dispatch.SysMsg.SystemMessage msg) { }
Expand Down Expand Up @@ -1325,6 +1326,7 @@ namespace Akka.Actor
public override void Suspend() { }
protected override void TellInternal(object message, Akka.Actor.IActorRef sender) { }
}
[System.ObsoleteAttribute("Not used. Will be removed in Akka.NET v1.5.")]
public class NameAndUid
{
public NameAndUid(string name, int uid) { }
Expand Down
6 changes: 3 additions & 3 deletions src/core/Akka.Remote/RemoteSystemDaemon.cs
Expand Up @@ -308,10 +308,10 @@ public override IActorRef GetChild(IEnumerable<string> name)
var n = 0;
while (true)
{
var nameAndUid = ActorCell.SplitNameAndUid(path);
if (TryGetChild(nameAndUid.Name, out var child))
var (s, uid) = ActorCell.GetNameAndUid(path);
if (TryGetChild(s, out var child))
{
if (nameAndUid.Uid != ActorCell.UndefinedUid && nameAndUid.Uid != child.Path.Uid)
if (uid != ActorCell.UndefinedUid && uid != child.Path.Uid)
return Nobody.Instance;
return n == 0 ? child : child.GetChild(name.TakeRight(n));
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/Akka.Remote/Serialization/LruBoundedCache.cs
Expand Up @@ -25,7 +25,7 @@ internal static class FastHash
/// <returns>A 32-bit pseudo-random hash value.</returns>
public static int OfString(string s)
{
var chars = s.ToCharArray();
var chars = s.AsSpan();
var s0 = 391408L; // seed value 1, DON'T CHANGE
var s1 = 601258L; // seed value 2, DON'T CHANGE
unchecked
Expand Down
6 changes: 2 additions & 4 deletions src/core/Akka.Tests/Actor/ActorSelectionSpec.cs
Expand Up @@ -76,12 +76,10 @@ private IActorRef AskNode(IActorRef node, IQuery query)
{
var result = node.Ask(query).Result;

var actorRef = result as IActorRef;
if (actorRef != null)
if (result is IActorRef actorRef)
return actorRef;

var selection = result as ActorSelection;
return selection != null ? Identify(selection) : null;
return result is ActorSelection selection ? Identify(selection) : null;
}

[Fact]
Expand Down
7 changes: 3 additions & 4 deletions src/core/Akka/Actor/ActorCell.Children.cs
Expand Up @@ -387,17 +387,16 @@ public bool TryGetSingleChild(string name, out IInternalActorRef child)
}
else
{
var nameAndUid = SplitNameAndUid(name);
if (TryGetChildRestartStatsByName(nameAndUid.Name, out var stats))
var (s, uid) = GetNameAndUid(name);
if (TryGetChildRestartStatsByName(s, out var stats))
{
var uid = nameAndUid.Uid;
if (uid == ActorCell.UndefinedUid || uid == stats.Uid)
{
child = stats.Child;
return true;
}
}
else if (TryGetFunctionRef(nameAndUid.Name, nameAndUid.Uid, out var functionRef))
else if (TryGetFunctionRef(s, uid, out var functionRef))
{
child = functionRef;
return true;
Expand Down
16 changes: 15 additions & 1 deletion src/core/Akka/Actor/ActorCell.cs
Expand Up @@ -479,10 +479,11 @@ protected void SetActorFields(ActorBase actor)
actor?.Unclear();
}
/// <summary>
/// TBD
/// INTERNAL API
/// </summary>
/// <param name="name">TBD</param>
/// <returns>TBD</returns>
[Obsolete("Not used. Will be removed in Akka.NET v1.5.")]
public static NameAndUid SplitNameAndUid(string name)
{
var i = name.IndexOf('#');
Expand All @@ -491,6 +492,19 @@ public static NameAndUid SplitNameAndUid(string name)
: new NameAndUid(name.Substring(0, i), Int32.Parse(name.Substring(i + 1)));
}

/// <summary>
/// INTERNAL API
/// </summary>
/// <param name="name">The full name of the actor, including the UID if known</param>
/// <returns>A new (string name, int uid) instance.</returns>
internal static (string name, int uid) GetNameAndUid(string name)
{
var i = name.IndexOf('#');
return i < 0
? (name, UndefinedUid)
: (name.Substring(0, i), SpanHacks.Parse(name.AsSpan(i + 1)));
}

/// <summary>
/// TBD
/// </summary>
Expand Down

0 comments on commit c21289e

Please sign in to comment.