C#

Checking Whether A Method Is Overridden

13 commentsWritten on January 11th, 2010 by
Categories: C#

One of the requirements for using Agatha’s Caching Layer is that your request types must override the Equals and the GetHashCode methods.  In order to limit the number of questions i’m going to receive about the caching layer not working correctly the amount of time people will waste on debugging when they don’t override these methods, i wanted to add a check to the initialization of Agatha which makes sure that each cacheable request type indeed overrides Equals and GetHashCode.

I actually had to think about how i could do this, but it turned out to be very simple.  The trick is basically to retrieve the MethodInfo of the method you're interested in, and then check the declaring type of that method.  If the method has been overridden, the declaring type will equal the type of the class you're checking.  If it hasn’t been overridden, the declaring type will be that of one of the base classes:

        private static bool CheckIfOverrideExists(Type type, string methodName)

        {

            var methodInfo = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);

 

            if (methodInfo == null)

            {

                return false;

            }

 

            return methodInfo.DeclaringType == type;

        }

 

Not sure if there’s a better way to do this (if so, please share) but for now, this is good enough for me.

Virtual Method Performance Penalty

21 commentsWritten on January 10th, 2010 by
Categories: C#, Performance

You often hear/read that one of the reasons why C# methods aren’t virtual by default is because of performance.  Calling a virtual method is more expensive than calling a regular instance method, because the CLR has to determine the correct override to call at runtime, instead of being able to simply call the instance method directly.  Another reason why virtual methods are more expensive to call is because they can never be inlined.

Is it really that much more expensive though? I ran a little experiment and i’d like to share the results with you.

Suppose you have the following 2 classes:

    public class MyClass

    {

        protected long someLong;

 

        public void IncreaseLong()

        {

            someLong++;

        }

 

        public virtual void VirtualIncreaseLong()

        {

            someLong++;

        }

    }

 

    public class MyDerivedClass : MyClass

    {

        public override void VirtualIncreaseLong()

        {

            someLong += 2;

        }

    }

 

As you can see, there is no difference between the IncreaseLong and VirtualIncreaseLong methods, except that the latter is virtual and the former is a regular instance method.  According to many people, calling VirtualIncreaseLong instead of IncreaseLong will be more expensive.  I also have a derived class which overrides the VirtualIncreaseLong method with a slightly different implementation.

If we call these methods a bunch of times (like 1000000000 times), we should notice quite a difference according to many people.

I wrote the following test code which calls these methods a bunch of times, times it, and outputs the results.

    class Program

    {

        const int numberOfTimes = 1000000000;

 

        static void Main(string[] args)

        {

            var myObject = new MyClass();

            var myDerivedObject = new MyDerivedClass();

 

            // we do this so there's no first-time performance cost while timing

            EnsureThatEverythingHasBeenJitted(myObject);

            EnsureThatEverythingHasBeenJitted(myDerivedObject);

 

            TestNormalIncreaseMethod(myObject);

            TestVirtualIncreaseMethod(myObject);

 

            TestNormalIncreaseMethod(myDerivedObject);

            TestVirtualIncreaseMethod(myDerivedObject);

 

            Console.ReadLine();

        }

 

        static void EnsureThatEverythingHasBeenJitted(MyClass theObject)

        {

            theObject.IncreaseLong();

            theObject.VirtualIncreaseLong();

        }

 

        static void TestNormalIncreaseMethod(MyClass theObject)

        {

            Console.WriteLine(string.Format("calling the IncreaseLong method of type {0} {1} times", theObject.GetType().Name, numberOfTimes));

 

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < numberOfTimes; i++)

            {

                theObject.IncreaseLong();

            }

            stopwatch.Stop();

 

            Console.WriteLine("Elapsed milliseconds: " + stopwatch.ElapsedMilliseconds);

        }

 

        static void TestVirtualIncreaseMethod(MyClass theObject)

        {

            Console.WriteLine(string.Format("calling the VirtualIncreaseLong method of type {0} {1} times", theObject.GetType().Name, numberOfTimes));

 

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < numberOfTimes; i++)

            {

                theObject.VirtualIncreaseLong();

            }

            stopwatch.Stop();

 

            Console.WriteLine("Elapsed milliseconds: " + stopwatch.ElapsedMilliseconds);

        }

    }

 

The output of running this code might surprise you.  On my machine, i got the following results when the code was compiled in debug mode:

manual_compile_debug

The difference between calling the regular instance method and the virtual method is quite small.  I’d even say it’s negligible.

When compiling in release mode, i got the following output:

manual_compile_optimized

I ran the test a bunch of times, and there was no consistent observable performance penalty when calling the virtual methods.  In fact, the virtual methods often performed faster than the regular instance methods and in most cases were equally fast.  I’m not claiming that virtual methods are faster than regular instance methods, but if there really was an extra real-world performance cost associated with virtual methods, it surely should be observable with this test code, no?

Obviously, this test isn’t scientific in any way.  But still, i think it does show that the so called performance cost associated with virtual methods is highly overrated.  There definitely will be cases where virtual methods are more expensive than regular instance methods, but i’m willing to bet that those cases are rare and that the vast majority of .NET developers will never be negatively impacted by it. 

Side note: have you ever noticed that most people who recommend to avoid virtual methods due to their performance cost never put the same emphasis on avoiding the cost of say, frequent remote operations?  Which is odd, since i wouldn’t be surprised if that would be the most common reason for performance problems with .NET applications.  Then again, that’s what you get when the biggest company pushing a platform advocates meaningless performance improvements while at the same time pushing bad architectural decisions/guidelines on the world because the resulting code is supposedly easier to write, use and maintain.

You can download the example code here so you can run the test yourself.