Skip to content

Conversation

Aaronontheweb
Copy link
Member

@Aaronontheweb Aaronontheweb commented Jan 27, 2018

API change and that may also have some performance impact (virtual methods can't be inlined by the compiler).

Rationale for this change is that it allows developers who are working on aspect-oriented add-ons for Akka.NET, such as yours truly, to be able to decorate 100% of actors with instrumentation and other goodies without having to have the user consume a custom actor base class or anything else that makes "infrastructure" a foreground concern. Also makes it possible to instrument built-in /system actors, which is part of my goal.

Using a custom ActorCell allows me to keep most of this stuff out of end-user code. However, at the moment there isn't a way for me to inject instrumentation at the time of processing a message, aside from doing it inside a custom IMessageQueue implementation used inside the Mailbox of the actor. I don't like the IMessageQueue approach namely because things like accessing a distributing tracing engine or a monitoring system seems like concerns of the actor, rather than its message-ordering infrastructure. Edit: there's also relevant pieces of information I can't access from within the IMessageQueue, such as the implementation type of the actor processing the message

Anyway, if there aren't any major objections or horrible performance implications (I could try to get cute with IL injection or something else) I think this would be a good way to provide some extensibility for this case.

@Horusiath
Copy link
Contributor

Can you share with some related performance benchmarks to track changes?

@Aaronontheweb
Copy link
Member Author

@Horusiath sure thing - I'll pull down the NBench numbers now and compare to the latest dev. This would impact all non-Router actors potentially, since the compiler can't inline virtual methods. It won't have a performance impact at all if the compiler wasn't inlining this method call before anyway.

@Aaronontheweb
Copy link
Member Author

ReceiveActor Throughput with this change

Totals

Metric Units Max Average Min StdDev
TotalCollections [Gen0] collections 177.00 156.08 154.00 6.30
TotalCollections [Gen1] collections 76.00 66.38 54.00 7.53
TotalCollections [Gen2] collections 23.00 3.00 1.00 6.06
[Counter] MessageReceived operations 30,000,000.00 30,000,000.00 30,000,000.00 0.00

Per-second Totals

Metric Units / s Max / s Average / s Min / s StdDev / s
TotalCollections [Gen0] collections 26.81 24.24 20.17 2.19
TotalCollections [Gen1] collections 13.14 10.37 8.03 1.87
TotalCollections [Gen2] collections 2.62 0.40 0.15 0.68
[Counter] MessageReceived operations 5,190,696.77 4,673,513.36 3,419,457.34 515,804.42

UntypedActor throughput with this change

Totals

Metric Units Max Average Min StdDev
TotalCollections [Gen0] collections 179.00 161.69 155.00 9.94
TotalCollections [Gen1] collections 77.00 64.15 54.00 9.17
TotalCollections [Gen2] collections 25.00 7.92 1.00 10.10
[Counter] MessageReceived operations 30,000,000.00 30,000,000.00 30,000,000.00 0.00

Per-second Totals

Metric Units / s Max / s Average / s Min / s StdDev / s
TotalCollections [Gen0] collections 27.56 23.43 20.69 2.22
TotalCollections [Gen1] collections 12.03 9.28 7.41 1.41
TotalCollections [Gen2] collections 3.15 1.02 0.14 1.24
[Counter] MessageReceived operations 5,333,699.44 4,370,527.77 3,547,353.74 572,698.39

@Aaronontheweb
Copy link
Member Author

N.B., UntypedActor performance should be higher than ReceiveActor generally, but due to the inherent imprecision of benchmarking concurrent code it looks like the average performance of UntypedActor was recorded as lower than ReceiveActor. Across a larger number of iterations this would not be true.

@Aaronontheweb
Copy link
Member Author

Aaronontheweb commented Jan 28, 2018

ReceiveActor Throughput on dev

Totals

Metric Units Max Average Min StdDev
TotalCollections [Gen0] collections 178.00 161.92 155.00 8.43
TotalCollections [Gen1] collections 76.00 69.85 56.00 7.28
TotalCollections [Gen2] collections 24.00 8.77 1.00 8.30
[Counter] MessageReceived operations 30,000,000.00 30,000,000.00 30,000,000.00 0.00

Per-second Totals

Metric Units / s Max / s Average / s Min / s StdDev / s
TotalCollections [Gen0] collections 24.57 21.60 18.08 2.00
TotalCollections [Gen1] collections 11.25 9.35 7.57 1.49
TotalCollections [Gen2] collections 2.68 1.07 0.14 0.89
[Counter] MessageReceived operations 4,755,540.72 4,023,773.24 3,081,462.12 515,596.24

UntypedActor Throughput on dev

Totals

Metric Units Max Average Min StdDev
TotalCollections [Gen0] collections 162.00 156.38 155.00 1.85
TotalCollections [Gen1] collections 73.00 62.23 55.00 6.57
TotalCollections [Gen2] collections 9.00 2.38 1.00 2.47
[Counter] MessageReceived operations 30,000,000.00 30,000,000.00 30,000,000.00 0.00

Per-second Totals

Metric Units / s Max / s Average / s Min / s StdDev / s
TotalCollections [Gen0] collections 27.08 22.36 20.45 1.73
TotalCollections [Gen1] collections 12.41 8.94 7.26 1.51
TotalCollections [Gen2] collections 1.17 0.33 0.13 0.33
[Counter] MessageReceived operations 5,242,170.27 4,290,378.12 3,910,750.47 351,846.32

@Aaronontheweb
Copy link
Member Author

The ReceiveActor numbers were lower on average on dev, but again that's due mostly to the inherent randomness of the virtual machines, load on the build agent, etc... So those figures don't tell us much.

The UntypedActor numbers on dev are much closer to what we recorded with this change.

TL;DR; it looks to me like this change doesn't have an effective impact on performance. The compiler probably wasn't inlining this method before, probably because the underlying base actor implementation that gets called inside the ActorCell.ReceiveMessage method can consist of many different ActorBase implementations, which would make it cost-prohibitive to inline. That's just a shoot-from-the-hip explanation on my part though.

Either way, I think this change is probably safe in terms of its performance impact on Akka.NET message processing throughput.

@Aaronontheweb
Copy link
Member Author

@Horusiath before we do this change though, let me do some testing locally today to ensure that this is the only API change necessary to introduce this instrumentation. I'd like to do this in one bite :p

@Aaronontheweb
Copy link
Member Author

Ok, can verify that this change gives me what I need to instrument all actor message processing. Good to go.

@Horusiath Horusiath merged commit 55bb020 into akkadotnet:dev Jan 29, 2018
@Aaronontheweb Aaronontheweb deleted the actorcell-receivemethod-protected branch January 29, 2018 20:46
@Aaronontheweb Aaronontheweb added this to the 1.3.4 milestone Feb 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants