I'm doing a bit of tinkering around the performance of virtual versus sealed people.

Below is my test code.

The output is

virtual total 3166ms
per call virtual 3.166ns
sealed total 3931ms
per call sealed 3.931ns

I have to do a problem because based on this the virtual call is faster compared to sealed call.

I'm running in Release mode with "Optimize code" switched on.

Edit: when running outdoors of Versus (like a console application) the occasions are near to a defunct warmth. however the virtual more often than not arrives in-front.

[TestFixture]
public class VirtTests
{

    public class ClassWithNonEmptyMethods
    {
        private double x;
        private double y;

        public virtual void VirtualMethod()
        {
            x++;
        }
        public void SealedMethod()
        {
            y++;
        }
    }

    const int iterations = 1000000000;


    [Test]
    public void NonEmptyMethodTest()
    {

        var foo = new ClassWithNonEmptyMethods();
        //Pre-call
        foo.VirtualMethod();
        foo.SealedMethod();

        var virtualWatch = new Stopwatch();
        virtualWatch.Start();
        for (var i = 0; i < iterations; i++)
        {
            foo.VirtualMethod();
        }
        virtualWatch.Stop();
        Console.WriteLine("virtual total {0}ms", virtualWatch.ElapsedMilliseconds);
        Console.WriteLine("per call virtual {0}ns", ((float)virtualWatch.ElapsedMilliseconds * 1000000) / iterations);


        var sealedWatch = new Stopwatch();
        sealedWatch.Start();
        for (var i = 0; i < iterations; i++)
        {
            foo.SealedMethod();
        }
        sealedWatch.Stop();
        Console.WriteLine("sealed total {0}ms", sealedWatch.ElapsedMilliseconds);
        Console.WriteLine("per call sealed {0}ns", ((float)sealedWatch.ElapsedMilliseconds * 1000000) / iterations);

    }

}

You're testing the results of memory alignment on code efficiency. The 32-bit JIT compiler has trouble producing efficient code for value types which are a lot more than 32 bits in dimensions. The main of the issue is the 32-bit GC heap allocator, it only promises alignment of allotted memory on addresses which are a multiple of four. That's an problem here, you're incrementing doubles. A double is efficient only when it's aligned with an address this is a multiple of 8. Same problem using the stack, just in case of local variables, it's also aligned simply to 4 on the 32-bit machine.

The amount CPU cache is internally organized in cache lines of 16 bytes each. There's a problem once the program reads a mis-aligned double. Especially one which straddles the finish of the cache line. Two lines need to be read and glued together. Mis-alignment is not uncommon within the 32-bit jitter, it's basically luck once the 'x' area is actually allotted with an address this is a multiple of 8. Whether it is not then 'x' and 'y' will be misaligned and one of these will straddle the cache line. How you authored the exam, that will either make VirtualMethod or SealedMethod reduced. Make certain you allow them to make use of the same area to obtain comparable results.

This is also true for code. Swap the code for that virtual and sealed test to randomly alter the outcome. I'd little difficulty making the sealed test a great deal faster this way.

It's also wise to run the timing test several occasions inside a loop, a minimum of 20. You'll probably then also take notice of the effect from the garbage collector moving the course object. The double could have a different alignment after, significantly altering the timing. Being able to access a double has 3 distinct timings, aligned on 8, aligned on 4 inside a cache line, and aligned on 4 across two cache lines. In fast to slow order.

First, you need to mark the technique sealed.

Next, offer an override towards the virtual method. Create a clear case of the derived class.

Like a third test, produce a sealed override method.

You can now start evaluating.

Edit: You need to most likely run this outdoors Versus.

Update:

Illustration of what i'm saying.

abstract class Foo
{
  virtual void Bar() {}
}

class Baz : Foo
{
  sealed override void Bar() {}
}

class Woz : Foo
{
  override void Bar() {}
}

Now test the phone call speed of Bar for a clear case of Baz and Woz. I additionally suspect member and sophistication visibility outdoors the set up may affect JIT analysis.