The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Windsor’s Interceptors and Performance

Posted by Davy Brion on May 9th, 2008

As i mentioned in a previous post, Windsor’s Interceptors are a great way to dynamically add behavior to a class. But what does it cost? There’s a lot of stuff going on behind to scenes to make that ‘magic’ work and surely, there’s a performance penalty involved somewhere.

I wanted to see what the cost of this approach is, so i created the following interface and class:

    public interface IDummy

    {

        void DoSomething();

    }

 

    public class Dummy : IDummy

    {

        public void DoSomething() {}

    }

Nothing special there… just a class with a method that doesn’t do anything. Combine that with an interceptor that doesn’t do anything:

    public class DummyInterceptor : Castle.Core.Interceptor.IInterceptor

    {

        public void Intercept(IInvocation invocation)

        {

            // do nothing, just proceed with the original call

            invocation.Proceed();

        }

    }

And then we configure the component and the interceptor like this:

      <component id="DummyInterceptor" service="Components.DummyInterceptor, Components"

                type="Components.DummyInterceptor, Components"

                lifestyle="transient" />

      <component id="Dummy" service="Components.IDummy, Components" type="Components.Dummy, Components">

 

        <interceptors>

          <interceptor>${DummyInterceptor}</interceptor>

        </interceptors>

 

      </component>

So what do we have now? We have a component which has a method that doesn’t do anything. And we’ve assigned an interceptor that doesn’t do anything… it just executes the original call without adding any behavior. Pretty useless, right? Right, but this is ideal to compare the runtime cost of merely intercepting calls to components. So the differences you’ll see below are without adding the extra behavior to your components. The differences you’ll see below are purely because each call is intercepted.

This is the code i used to test the difference:

        [Test]

        public void TestDummyPerformance()

        {

            Time(() => CallMethodXAmountOfTimes(new Dummy(), 1000000));

            Time(() => CallMethodXAmountOfTimes(Container.Resolve<IDummy>(), 1000000));

        }

 

        private void CallMethodXAmountOfTimes(IDummy dummy, int times)

        {

            for (int i = 0; i < times; i++)

            {

                dummy.DoSomething();   

            }

        }

 

        private void Time(Action action)

        {

            DateTime before = DateTime.Now;

            action();

            Console.WriteLine("Time elapsed : " + (DateTime.Now - before));

        }

First, we call the DoSomething method on a regular Dummy instance 1 million times. The time that takes is written to the Console. Then we call the DoSomething method (again, 1 million times) on an IDummy instance provided by the container, which has our interceptor attached to it (note: when you do not have an interceptor attached, there is NO runtime penalty!).

The output of the test (on my machine) is the following:

Time elapsed : 00:00:00.0100144
Time elapsed : 00:00:00.5808352

As you can see, the second time (using the intercepted instance) is significantly slower than using a concrete instance. But honestly, this is after calling the method one million times. And it only takes about half a second (on a virtualized Windows XP running on a cheap Macbook ;) ) to call this method one million times. In a real-world scenario, you probably won’t notice any performance hit unless the code that is intercepted is in a long, tight loop or something like that.

Having said that, i do think using the interceptor approach should be a temporary action in most cases. If you have to debug weird issues, i think adding an extensive logging/tracing interceptor to your components can be extremely valuable without having to pollute your code with logging/tracing statements. But if you want certain behavior to be added to your classes without it being configurable, there certainly are better options to use. PostSharp is a library which enables Aspect Oriented Programming without performance penalties. This approach basically allows you to add specific behavior to methods or classes by placing attributes on them. PostSharp will then modify the compiled byte-code to add the ‘aspects’ (the behavior that you want to add) to the real code. I’ll write a post about this approach soon ;)

One Response to “Windsor’s Interceptors and Performance”

  1. Gael Fraiteur Says:

    I would not say that PostSharp is without performance overhead. Actually, Windsor generates proxies using Reflection Emit, so once the proxy is emitted, Windsor is as fast as PostSharp.

    The big difference is somewhere else: Windsor enables AOP typically only on service boundaries, the set of available aspects is more limited, it forces you to use factories.

    To be more precise, if you use PostSharp Core to inject ad-hoc MSIL instructions, there will be no difference in performance w.r.t. hand-tuned code. But if you use PostSharp Laos, the high-level library offering a similar performance of functionality as Windsor, performance will be similar — since the level of abstraction is similar.

    Happy PostSharping!

    Gael

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>