I said in a previous post about there being some things to watch out for when using proxies… Here’s what I’ve seen, there’s probably more, add your experiences to the comments 🙂
This is really only an issue if you violate the Liskov Substitution Principle (LSP), but it’s worth knowing as it can catch you out. Have a look at this test:
As you can see, when we’re applying an aspect the instance we get out of the container is not a TestServiceImpl, it’s a proxy class… The proxy class (which is dynamically generated) implements the service interface (ITestService) and aggregates the implementation (TestServiceImpl). It then forwards on the calls to the implementation. As I said, it’s normally a bad smell to do what I’m doing in this test, but it’s good to be aware of.
Note: If you want to get hold of the real thing, the proxy class also implements IProxyTargetAccessor which you can then use to get at the real thing… However, I’d suggest if you’re doing this they’d better be a good reason!
Another thing to consider is performance… Here’s a test to highlight the performance impact:
Here are the results (doesn’t really matter what box I ran these tests on – I just want to highlight the difference).
|Action||With (ms)||Without (ms)||With (ticks)||Without (ticks)|
|10,000 method calls||48||0||173,303||369|
The first resolve is much slower because that’s when we IL emit the class which is our proxy (I’m guess I’ve not looked at the code). This is only ever done once for the lifetime of the process so think of it just like ASP.Net complication… If you want your first call to be quick, make sure you resolve it before you make your real call…
10,000 resolutions takes about 452ms slower 0.0452 ms per call slower…
10,000 method calls takes 48ms, which works out at 0.0048ms per call… To compare this to a normal method call we need to use the ticks (because as you can see calling a method is pretty darn quick!). The difference is massive as you can see.
So is this performance impact important? It depends. For me, no. The difference pails into insignificance when you consider what the implementations are actually doing. The application I’m building is multi tiered, it eventually sticks something in or gets something out of a database in response to someone calling a web service. I have no idea on average how many resolutions / method invocations there are before I get to the point where my data is ready to be stuffed across the wire to a web service, across the network again to a database server, then into the database, all in a transaction which needs committing…. I’m pretty confident that, as a percentage, the overhead of the aspect is insignificant. However, if this was in a sort algorithm then I’d be nuts to use an aspect due to the performance – but I’d be nuts anyway!
It’s worth being aware of the fact that AOP has a performance impact. People can use it as an argument not to use it. But, remember your context… A method call is VERY quick. A method call with a proxy in the way is comparatively MUCH slower. But, how much slower in the context of the entire operation? Context is king.
Lastly… One thing you may notice is a fun stack trace when debugging. You’ll get an extra couple of items in the stack for each intercepted method call, which can make reading the stack trace in the debugger a bit more difficult. Also, when you hit F11 to step in you’ll disappear off into Windsor… However, if you’re following TDD then, when you do crack out the debugger (many practitioners argue that it’s rare if not bad) aspects won’t be applied (you’re testing one thing at a time remember). If you’re debugging an integration test then you can turn off aspects to get a cleaner stack (if it’s really that intrusive). So in the grand scheme of things I don’t think this is a massive issue.