Skip to content

Conversation

@Aaronontheweb
Copy link
Member

@Aaronontheweb Aaronontheweb commented Mar 20, 2025

Changes

A continuation of @mhbuck 's work on #7498 - addressing some of the comments I made in my review of that PR.

Checklist

For significant changes, please ensure that the following have been completed (delete if not relevant):

Latest dev Benchmarks

Warming up...
OSVersion:              Unix 6.9.3.76060903
ProcessorCount:         16
ClockSpeed:             0 MHZ
Actor Count:            32
Messages sent/received: 30000000  (3e7)
Is Server GC:           True
Thread count:           34

ActorBase    first start time:  5.26 ms
ReceiveActor first start time: 23.66 ms

            ActorBase                          ReceiveActor
Throughput, Msgs/sec, Start [ms], Total [ms],  Msgs/sec, Start [ms], Total [ms]
         1, 38809000,      29.91,     803.68,  40000000,      39.27,     789.67
         5, 111940000,      36.77,     305.24,  81521000,      37.11,     405.86
        10, 155440000,      37.39,     231.11,  125523000,      31.82,     271.47
        15, 114503000,      15.98,     278.62,  103448000,      29.42,     320.20
        20, 111940000,      25.88,     294.62,  117647000,      35.42,     291.30
        30, 120967000,      36.27,     284.70,  146341000,      37.60,     243.32
        40, 126050000,      32.40,     271.09,  102040000,      39.20,     333.53
        50, 139534000,      34.91,     250.29,  115830000,      16.13,     275.69
        60, 189873000,      22.99,     181.19,  172413000,      26.88,     201.12
        70, 118577000,      29.70,     283.05,  134529000,      40.82,     264.45
        80, 124481000,      32.97,     274.01,  82191000,      17.53,     383.42
        90, 188679000,      39.92,     199.11,  96774000,      37.45,     347.60
       100, 144230000,      33.66,     241.75,  158730000,      32.44,     222.13
       200, 129310000,      20.43,     253.34,  152284000,      17.32,     214.55
       300, 161290000,      28.14,     214.60,  138248000,      35.96,     253.21
       400, 118577000,      32.60,     285.81,  77720000,      26.09,     413.01
       500, 156250000,      34.92,     227.67,  149253000,      34.76,     236.75
       600, 99337000,      23.40,     325.72,  174418000,      20.22,     192.47
       700, 143540000,      34.79,     243.97,  140845000,      17.50,     231.35
       800, 116731000,      37.86,     295.16,  170454000,      34.80,     211.45
       900, 110701000,      35.92,     307.24,  151515000,      10.00,     208.90

This PR's Benchmarks

Warming up...
OSVersion:              Unix 6.9.3.76060903
ProcessorCount:         16
ClockSpeed:             0 MHZ
Actor Count:            32
Messages sent/received: 30000000  (3e7)
Is Server GC:           True
Thread count:           34

ActorBase    first start time:  5.85 ms
ReceiveActor first start time:  6.00 ms

            ActorBase                          ReceiveActor
Throughput, Msgs/sec, Start [ms], Total [ms],  Msgs/sec, Start [ms], Total [ms]
         1, 31645000,      40.09,     988.82,  35799000,      38.95,     877.62
         5, 84745000,      43.59,     398.48,  82191000,      39.65,     405.40
        10, 107913000,      31.50,     309.77,  76335000,      30.32,     424.03
        15, 123966000,      20.96,     263.67,  113207000,      39.87,     305.08
        20, 104895000,      16.51,     303.17,  111524000,       2.29,     272.20
        30, 77922000,      26.90,     412.14,  112359000,       5.60,     273.17
        40, 119521000,      37.98,     289.45,  119521000,      30.81,     282.05
        50, 126050000,      16.92,     255.38,  103806000,      32.32,     321.54
        60, 103448000,      22.38,     312.44,  120481000,       3.22,     252.64
        70, 121951000,      39.56,     285.84,  110701000,      19.06,     290.94
        80, 115384000,      12.79,     273.62,  115384000,       6.60,     267.36
        90, 191082000,      28.91,     186.07,  196078000,       2.08,     155.28
       100, 146341000,       5.77,     211.14,  133928000,      15.79,     240.20
       200, 107913000,      38.09,     317.01,  115830000,      37.36,     296.99
       300, 133333000,       8.52,     234.44,  157894000,       6.51,     196.83
       400, 138888000,      38.45,     255.08,  143540000,       3.36,     212.82
       500, 122950000,       2.11,     246.35,  157068000,      22.83,     214.62
       600, 126582000,      36.50,     274.22,  160427000,      13.31,     201.11
       700, 133928000,      29.47,     253.68,  106382000,      21.86,     304.33
       800, 93457000,       1.91,     323.81,  137614000,      13.33,     231.39
       900, 153061000,       8.33,     204.53,  165745000,       3.36,     184.70
Done..                             

@Aaronontheweb Aaronontheweb added akka-actor AOT Ahead-of-Time (AOT) Compilation labels Mar 20, 2025
Copy link
Member Author

@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.

Detailed my changes - going to work on getting some benchmark data.

[Theory]
[InlineData(true)]
[InlineData(false)]
public void Given_TypedReceiveHandler_can_match_interface_on_ConcreteTypes(bool usePredicate)
Copy link
Member Author

Choose a reason for hiding this comment

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

This spec at the bottom covers two scenarios:

  1. Tests the preservation of Akka.NET (,1.5] Receive<T> declaration order
  2. Asserts that your Type-assignability code from ReceiveActor - Removing MatchBuilder and making use of handlers. #7498 works

HandleAny = null;
}

private List<ITypeHandler> TypedHandlers { get; }
Copy link
Member Author

Choose a reason for hiding this comment

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

Moved from a Dictionary to a List in order to guarantee that declared Receive<T> order matches our handling order, which is an important behavioral requirement

TypedHandlers.Add(CreateTypeHandler(messageType, shouldHandlePredicate, handler));

// If the message type is object, then we need to track that we have added a handler with no predicate.
if (messageType == typeof(object) &&
Copy link
Member Author

Choose a reason for hiding this comment

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

In theory we could also do this from AddGenericReceiveHandler<T> but IMHO we're better off authoring an analyzer and flagging this issue at compilation - we have the ability to do that easily now through Akka.Analyzers.

HandleAny = handler;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Copy link
Member Author

Choose a reason for hiding this comment

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

A little prayer to the compiler to make this faster

bool TryHandle(object message);
}

internal sealed class WeaklyTypedPredicateHandler : ITypeHandler
Copy link
Member Author

Choose a reason for hiding this comment

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

Better to have 4 purpose-built ITypeHandlers so we can keep the TryHandle as slim as possible. If it turns out that a predicate null check has lower perf impact that the interface dispatcher overhead then we can pare this down to 2 implementations. If we get rid of the non-generic Receive methods from receive actors then we can get this down to a single implementation and remove the interface altogether.

@Aaronontheweb
Copy link
Member Author

lol ReceiveActor<T> cracked 196m msg/s in this PR.

@Aaronontheweb
Copy link
Member Author

Getting some BDN numbers too since we have a PingPong version that uses ReceiveActors in there...

@Aaronontheweb
Copy link
Member Author

dev


BenchmarkDotNet v0.13.12, Pop!_OS 22.04 LTS
13th Gen Intel Core i7-1360P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 9.0.100
  [Host]     : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
  Job-ZNMNMQ : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2

InvocationCount=1  LaunchCount=10  RunStrategy=Monitoring
UnrollFactor=1  WarmupCount=10

Method Mean Error StdDev Req/sec
Actor_ping_pong_single_pair_in_memory 304.2 ns 3.27 ns 9.65 ns 3,286,911.61

This PR

                                                                                             
BenchmarkDotNet v0.13.12, Pop!_OS 22.04 LTS                                                  
13th Gen Intel Core i7-1360P, 1 CPU, 16 logical and 12 physical cores                        
.NET SDK 9.0.100                                                                             
  [Host]     : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2                                 
  Job-XWNBWJ : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2                                 
                                                                                             
InvocationCount=1  LaunchCount=10  RunStrategy=Monitoring                                    
UnrollFactor=1  WarmupCount=10                                                               
                                                                                             
Method Mean Error StdDev Req/sec
Actor_ping_pong_single_pair_in_memory 298.6 ns 5.20 ns 15.34 ns 3,349,127.23

@Aaronontheweb
Copy link
Member Author

I need to adjust the benchmark config with BDN to look a bit closer to what we did for Akka.Streams.Kafka, but overall it doesn't look like these changes hurt our perf at all.

@Aaronontheweb Aaronontheweb marked this pull request as ready for review March 20, 2025 20:39
@Aaronontheweb
Copy link
Member Author

So I ran this PR against #7458 and it didn't reduce the AOT warnings at all, but for a very obvious reason: the config and Props stuff that happens before we even launch the ReceiveActor is causing the executable to crash. We'll need to get a version of #7431 and rewriting Props to not use NewExpressions in-place before we can even see the AOT benefit from this 🙃

@Aaronontheweb
Copy link
Member Author

Superseded via #7557

@Aaronontheweb Aaronontheweb deleted the ReceiveActorHandlers-ordering branch March 21, 2025 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

akka.net v1.6 Akka.NET v1.6-related issues akka-actor AOT Ahead-of-Time (AOT) Compilation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants