Performance Consideration: Passthrough Aspects

Mike-EEE's Avatar


13 Sep, 2016 03:23 PM


I have been working with a pattern with PostSharp, and I have been running into a performance issue that I hope you can consider and maybe rectify. This pattern has emerged based on a limitation that I have found with using instance-level method interception aspects.

I have created a project with a test that shows different results, you can find that here.

To start, what I was doing before I found this limitation was using an aspect with no OnInvoke that created an instance where the OnInvoke was implemented. (Sample implementation here)

In this case, the method-level aspect would simply "pass through" its call in the case of an instance not meeting a criteria, and not running any additional instructions (which impedes performance).

Now that I can no longer do this, I have to use the next best pattern and use a method-level aspect in conjunction with an instance-level aspect. This can be seen in the sample project above in GitHub. I have created a test that runs performance metrics, and I wanted to share them here:

Test                        | Average |  Median |    Mode
RunBasicCoreCommand         | 00.0000 | 00.0000 | 00.0000
RunAspectCommand            | 00.0005 | 00.0005 | 00.0004
RunExtensibleCommand        | 00.0006 | 00.0005 | 00.0005
RunEnabledExtensibleCommand | 00.0006 | 00.0005 | 00.0005

First, my performance metrics are not super-high/production quality, but they give some reference/context. Each "test" is a method, which is run at 10,000 times, for 100 times, and the averages are calculated from there.

  • RunBasicCoreCommand is the simplest. It simply runs a regular empty method. This is 0 (or 1 in some cases)ms. Pretty expected.
  • RunAspectCommand simply adds an empty aspect to a method. The shocking discovery here is that this increases overhead by 5x (in the case of a 1ms run on the first test). EDIT: Please note that this appears to be an n-level impact, meaning the increase is per aspect. So, if you apply 2 aspects, the total time is roughly 9-10ms, 3 aspects is 14-15ms, etc...
  • RunExtensibleCommand and RunEnabledExtensibleCommand demonstrate how I am implementing the pass-through pattern (currently). Essentially there is a base class with aspect(s) applied, and it checks to see if a certain interface (that is implemented via an instance aspect) that is applied before it runs its code.

You can see that this adds maybe another 1ms to the overall time.

So I guess the ask/suggestion here is perhaps investigating a way to improve the performance in this scenario. In my case, ExtensibleCommandBase is actually CommandBase in my framework. That means that every command that extends from this base class is taking this performance hit, which is a drag, currently.

It would be awesome and incredibly valuable to see this addressed somehow, and/or if you can recommend some guidance to maybe work around this and/or improve my current implementation.

Thank you for any assistance/consideration,

  1. 1 Posted by Mike-EEE on 17 Sep, 2016 02:33 PM

    Mike-EEE's Avatar

    There might be more information in the above than is really necessary (who me?). To really sum up this issue, in a tweet-like format:

    • PostSharp currently impacts performance with each applied aspect adding roughly 5-6ms per aspect, before the introduction of any custom logic. It would be great to see this reduced to a much lesser amount.

    Probably more characters in a tweet, but hopefully that better summarizes what I was pawing after. I also noticed that there is a run-time performance vote/idea on uservoice:

    I have made mention of this issue there in the comments in hopes that this will be captured/addressed during that story. I will close this discussion now, accordingly.

  2. Mike-EEE closed this discussion on 17 Sep, 2016 02:33 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts


? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac