Reflection vs. dynamic code generation

For the code I'm writing for my job I need to set a lot of properties based on values read from external files. Not only the values are dynamic, so are the property names. To prevent this turning into a giant switch statement that needs to be updated every time I add a property, I wanted to use reflection.

Of course, I've often heard that reflection is slow, and this property setting operation will be done a lot. But, I'm also a big proponent of preventing premature optimization, so I decided to build a simple test, where I pitted reflection against using a dynamically generated method, using .Net 2.0's supercool DynamicMethod class which allows for light-weight code generation. Below is the code I used for this test:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using System.Diagnostics;

namespace DynamicMethodTest
{
    class Foo
    {
        private string _bar;

        public string Bar
        {
            get { return _bar; }
            set { _bar = value; }
        }
    
    }

    class Program
    {
        delegate void TestDelegate(Foo arg);

        static void Main(string[] args)
        {
            TestDelegate test = CreateMethod();
            Stopwatch s = new Stopwatch();
            Foo f = new Foo();
            s.Start();
            for( int x = 0; x < 1000000; ++x )
                test(f);
            s.Stop();
            Console.WriteLine("Dynamic method: {0}", s.Elapsed);

            s.Reset();
            Type t = f.GetType();
            PropertyInfo info = t.GetProperty("Bar");
            s.Start();
            for( int x = 0; x < 1000000; ++x )
            {
                info.SetValue(f, "Hello, World!", null);
            }
            s.Stop();
            Console.WriteLine("Reflection: {0}", s.Elapsed);


            Console.ReadKey();
        }

        static TestDelegate CreateMethod()
        {
            Type[] args = new Type[] { typeof(Foo) };
            DynamicMethod method = new DynamicMethod("Test", null, args, typeof(Program));
            ILGenerator gen = method.GetILGenerator();
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldstr, "Hello, World!");
            MethodInfo m = typeof(Foo).GetProperty("Bar").GetSetMethod();
            gen.EmitCall(OpCodes.Call, m, null);
            gen.Emit(OpCodes.Ret);

            return (TestDelegate)method.CreateDelegate(typeof(TestDelegate));
        }
    }
}

And this is the result:
Dynamic method: 00:00:00.0326159
Reflection: 00:00:05.8752216

As you can see, reflection is not just slower, it's orders of magnitude slower! This result far exceeds the speed difference I was expecting. I tried to find something wrong with the benchmark, something that would skew the result, but I cannot find anything at first glance (if anyone sees a problem please let me know).

So it would appear that if you have to do a lot of reflection, taking the time to implement dynamic code generation can really pay off.

It's important not to underestimate the power of DynamicMethod. In my case the configuration file containing the properties to set can change without the application restarting; this means that I will need to recreate the dynamic methods and discard those I don't need anymore. And that's precisely the biggest advantage to DynamicMethod; it's discardable. In .Net 1.1, if you wanted dynamic code generation, you had to generate a complete in-memory assembly, and if you're familiar with the CLR you'll know that assemblies (generated or otherwise) cannot be unloaded. That would mean that to prevent a memory leak I would have to place the generated assembly in a separate AppDomain (which you can unload, also unloading all the assemblies contained in it), with all the hassle and performance implications that entails. Thanks to DynamicMethod, none of that is necessary.

Categories: Programming
Posted on: 2006-12-20 23:56 UTC.

Comments

Tia

2014-05-15 15:20 UTC

Hello. I wanted to ask you a question about your current view on reflection versus dynamic code generation. Is there an email address to which I may submit my question?

Add comment

Comments are closed for this post. Sorry.

Latest posts

Categories

Archive

Syndication

RSS Subscribe