I frequently hear claims that Reflection in .NET is slow.  The discovery of the various metadata element of a type definitely is expensive, but after that cost is incurred, is the invocation of those elements any slower than native code?  I’ve often wondered, but never did any tests of my own.

Here is one quick speed test:

SpeedWriter

    public class SpeedWriter : IDisposable
    {
        private readonly Stopwatch _watch = new Stopwatch();
        private readonly string _description;

        public SpeedWriter(string description)
        {
            _description = description;
            _watch.Start();
        }

        public void Dispose()
        {
            _watch.Stop();

            long duration = _watch.ElapsedMilliseconds;

            Console.WriteLine(string.Format("{0} -- Milliseconds: {1}", _description, duration));
        }
    }

Foo

Some silly object that I can act upon in my tests

    public class Foo
    {
        public string Bar { get; set; }

        public void DoSomething(int x, int y)
        {
            // do something that the compiler won't optimize away
            int sum = x + y;

            if ( sum > 1000 )
            {
                Console.WriteLine("You're exceeded 100!");
            }

        }
    }

 

DoReflectionTest

        private static void DoReflectionTest()
        {
            Console.WriteLine("--------------- Reflection Test Begin ------------------");
                        
            PropertyInfo property = typeof (Foo).GetProperty("Bar");
            MethodInfo method = typeof (Foo).GetMethod("DoSomething");

            Foo foo = new Foo();

            using ( new SpeedWriter("Foo.Bar Setter Test..."))
            {
                int counter = 0;

                while ( counter < 1000 ) // do this a few times
                {
                    property.SetValue(foo, Guid.NewGuid().ToString(), null);
                    counter++;
                }
            }

            using (new SpeedWriter("Foo.Bar Getter Test..."))
            {
                int counter = 0;

                while (counter < 1000) // do this a few times
                {
                    property.GetValue(foo, null);
                    counter++;
                }
            }
            
            using (new SpeedWriter("Foo.Write Method-Invoke Test..."))
            {
                int counter = 0;

                while (counter < 1000) // do this a few times
                {
                    method.Invoke(foo, new object[] { counter, 1 } );
                    counter++;
                }
            }

            Console.WriteLine("---------------- Reflection Test End -------------------");
        }

DoNativeCodeTest

        private static void DoNativeCodeTest()
        {

            Console.WriteLine("--------------- Native Code Test Begin ------------------");

            Foo foo = new Foo();

            using (new SpeedWriter("Foo.Bar Setter Test..."))
            {
                int counter = 0;

                while (counter < 1000) // do this a few times
                {
                    foo.Bar = Guid.NewGuid().ToString();
                    counter++;
                }
            }

            using (new SpeedWriter("Foo.Bar Getter Test..."))
            {
                int counter = 0;

                while (counter < 1000) // do this a few times
                {
                    string bar = foo.Bar;
                    counter++;
                }
            }

            using (new SpeedWriter("Foo.Write Method-Invoke Test..."))
            {
                int counter = 0;

                while (counter < 1000) // do this a few times
                {
                    foo.DoSomething(counter, 1);
                    counter++;
                }
            }

            Console.WriteLine("---------------- Native Code Test End -------------------");
        }

 

Conclusion

There’s definitely a difference:

image

I’d like to do some more tests to better understand the difference precisely.  I’d also like to create a test case for a dynamic-method implementation to see how close it is to native code.