Dynamic methods in .NET

Using reflection to invoke methods which are not known at compile time might be problematic in performance critical applications. It is roughly 2.5-3.0 times slower than direct method calls. Here’s a sample test I’ve conducted:

class Program
    {
        [DllImport("kernel32.dll")]
        static extern void QueryPerformanceCounter(ref long ticks);

        static PropertyInfo _intProp = typeof(Foo).GetProperty("IntProp", BindingFlags.Public | BindingFlags.Instance);

        static void Main(string[] args)
        {
            Foo foo = new Foo { IntProp = 10 };
            const int COUNT = 1;
            Console.WriteLine(Measure(() => ReadPropertyWithReflection(foo), COUNT));
            Console.WriteLine(Measure(() => ReadPropertyDirectly(foo), COUNT));
        }

        static void ReadPropertyWithReflection(Foo foo)
        {
            int intProp = (int)_intProp.GetValue(foo, null);
        }

        static void ReadPropertyDirectly(Foo foo)
        {
            int intProp = foo.IntProp;
        }

        static long Measure(Action action, int count)
        {
            long startTicks = 0;
            QueryPerformanceCounter(ref startTicks);
            for (int i = 0; i < count; i++)
            {
                action();
            }
            long endTicks = 0;
            QueryPerformanceCounter(ref endTicks);
            return endTicks - startTicks;
        }

        class Foo
        {
            public int IntProp { get; set; }
        }
    }

Here are the results:

Method CPU units
Direct method invocation 796
Reflection method invocation 1986

So using reflection to perform a single property read is 2.5 slower than direct property access.

Dynamic methods can be used to generate and execute a method at run time, without having to declare a dynamic assembly and a dynamic type to contain the method. They are the most efficient way to generate and execute small amounts of code. Here’s an example of using DynamicMethod class to generate a getter for a given property:

static Func<Arg0, TReturn> EmitGetter<Arg0, TReturn>(PropertyInfo propertyInfo)
    {
        MethodInfo mi = propertyInfo.GetGetMethod();
        DynamicMethod dm = new DynamicMethod(
            "_get",
            typeof(TReturn),
            new Type[] { typeof(Arg0) },
            propertyInfo.DeclaringType);

        ILGenerator il = dm.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
        il.EmitCall(OpCodes.Callvirt, mi, null);
        il.Emit(OpCodes.Ret);

        return (Func<Arg0, TReturn>)dm.CreateDelegate(typeof(Func<Arg0, TReturn>));
    }

Now using this method we can emit a getter method from a PropertyInfo at run time and execute the returned delegate:

Func<Foo, int> getter = EmitGetter<Foo, int>(_intProp);
    Console.WriteLine(Measure(() => getter(foo), COUNT));

And here are the final results I’ve obtained using three different methods to read a property value:

Method CPU units
Direct method invocation 796
Dynamic method invocation 1190
Reflection method invocation 1986

Leave a comment

Your email address will not be published. Required fields are marked *