Reflection.InvokeMember vs Dynamic vs Static Binding Performance

In yesterday’s post, Visitor Pattern Revisited with C# 4, I talked about a new way to implement the visitor pattern with C# 4. In my article, I omitted one way to implement the pattern in pre- C# 4.0 versions and that was reflection.

You can implement the Serialize method with reflection as follows:

public void SerializeWithReflection(Product p)
{
    typeof (ProductSerializer).InvokeMember("Serialize", BindingFlags.Default | BindingFlags.InvokeMethod, 
        null, this, new [] {p});
}

You can see the drawback with this that the name of the method is not strongly typed, which makes it prone to refactoring errors. If you are using this approach, make sure that your unit tests are covering it.

I decided to a benchmark of all three methods, just to see what kind of performance you get with dynamic binding vs the other available methods.

Here is the full code:

    public abstract class Product { }
    public class Book : Product { }
    public class Record : Product { }
    public class Movie : Product { }

    public class ProductSerializer
    {
        public void Serialize(Book b) { }
        public void Serialize(Record b) { }
        public void Serialize(Movie b) { }

        public void SerializeWithDynamic(Product p)
        {
            Serialize((dynamic)p);
        }


        public void SerializeWithReflection(Product p)
        {
            typeof(ProductSerializer).InvokeMember("Serialize", BindingFlags.Default | BindingFlags.InvokeMethod,
                null, this, new[] { p });
        }

        public void SerializeWithStaticBinding(Product p)
        {
            if (p is Book) Serialize(p as Book);
            if (p is Record) Serialize(p as Record);
            if (p is Movie) Serialize(p as Movie);
        }
    }

    class Program
    {
        const int NumRepetitions = 10000000;
        static TimeSpan Benchmark(Action action)
        {
            var stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < NumRepetitions; i++)
                action.Invoke();
            return stopwatch.Elapsed;
        }

        static void Main(string[] args)
        {
            Product b = new Movie();
            var serializer = new ProductSerializer();
            Console.WriteLine("SerializeWithReflection: " + Benchmark(() => serializer.SerializeWithReflection(b)));
            Console.WriteLine("SerializeWithDynamic: " + Benchmark(() => serializer.SerializeWithDynamic(b)));
            Console.WriteLine("SerializeWithStaticBinding: " + Benchmark(() => serializer.SerializeWithStaticBinding(b)));
        }
    }

And this is the output:

SerializeWithReflection:    00:00:40.9627807
SerializeWithDynamic:       00:00:00.5167343
SerializeWithStaticBinding: 00:00:00.2959728

You can see that reflection, by far is the slowest. It is slower than dynamic binding by almost two orders of magnitude. Dynamic binding is only about 2x slow as static binding. Keep in mind that this is for 10000000 repetitions, so it might not mean much in the grand scheme of things when it comes to performance. However realistically there is no clear gain to write long static binding code instead of using the much more compact dynamic code. I see the biggest gain in compact, clean and strongly typed code rather than performance when compared to other approaches.

Advertisements

One thought on “Reflection.InvokeMember vs Dynamic vs Static Binding Performance

  1. for fair results, you should cache the reflected method instead of determining it every time.
    this brings the result closer to the dynamic performance

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s