Virtual Method Performance

|

Bart J.F. De Smet just blogs about the performance discrepancy when calling vitual methods and non-virtual methods, in his original testing code, he just compares calling virual methods and non-virtual methods through class-based references, actually calling virtual methods through interface-based references will also incur additional performance overhead, I modify his original code to include the testing snippet for calling virtual methods through interface-based reference:

using System;
using System.Diagnostics;

interface IFoo
{
    void Do();
}

class Virt : IFoo
{
    public virtual void Do() { }
    public void DoIt() { }

    static void Main()
    {
        Virt v = new Virt();

        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 1000000000; i++)
            v.DoIt();
        sw.Stop();
        Console.WriteLine("Calling non-virtual method:{0}", sw.Elapsed);

        sw.Reset();
        sw.Start();
        for (int i = 0; i < 1000000000; i++)
            v.Do();
        sw.Stop();
        Console.WriteLine("Calling virtual method using class-based reference:{0}", sw.Elapsed);

        sw.Reset();
        sw.Start();
        IFoo f = v as IFoo;
        for (int i = 0; i < 1000000000; i++)
            f.Do();
        sw.Stop();
        Console.WriteLine("Calling virtual method using interface-based reference:{0}", sw.Elapsed);
    }
}
 

When compiling the above code using "csc /o /target:exe test.cs", and running it, I get the following output from the console:

Calling non-virtual method:00:00:01.6662637
Calling virtual method using class-based reference:00:00:03.9324559
Calling virtual method using interface-based reference:00:00:05.6118531

And when examining the compiled MSIL code using ildasme.exe, the callvirt opcode is used in the three testing snippets:

IL_0017: callvirt instance void Virt::DoIt() //v.DoIt()

IL_0054: callvirt instance void Virt::Do() //v.Do()

IL_0096: callvirt instance void IFoo::Do() //f.Do()

You can see that the three callvirt calls will result in three different performance results, I don't plan to explain why it works this way, because all I know about virtual method dispatching in CLR is learnt from Don Box's Essential .NET: Common Language Runtime, this book give a complete treatment on virtual methods and how it works.

0 comments: