user1968030
user1968030

Reputation:

The overall performance where the method is placed in a code

Consider this code:

namespace FastReflectionTests
{
    public class Test
    {
        public void Method1()
        {
            var x = 10;
            var y = 20;
             if (x == 10 && y == 20)
            {

            }
        }

        public void Method2()
        {
            var x = 10;
            var y = 20;
            if (x == 10 && y == 20)
            {

            }
        }
    }
}

Now consider the IL Code:

This is method1:

    instance void Method1 () cil managed 
    {
    // Method begins at RVA 0x3bd0
    // Code size 17 (0x11)
    .maxstack 2
    .locals init (
    [0] int32 x,
    [1] int32 y
    )

    IL_0000: ldc.i4.s 10
    IL_0002: stloc.0
    IL_0003: ldc.i4.s 20
    IL_0005: stloc.1
    IL_0006: ldloc.0
    IL_0007: ldc.i4.s 10
    IL_0009: bne.un.s IL_0010

    IL_000b: ldloc.1
    IL_000c: ldc.i4.s 20
    IL_000e: pop
    IL_000f: pop

    IL_0010: ret
    } // end of method Test::Method1

This is method2:

    instance void Method2 () cil managed 
    {
    // Method begins at RVA 0x3bf0
    // Code size 17 (0x11)
    .maxstack 2
    .locals init (
    [0] int32 x,
    [1] int32 y
    )

    IL_0000: ldc.i4.s 10
    IL_0002: stloc.0
    IL_0003: ldc.i4.s 20
    IL_0005: stloc.1
    IL_0006: ldloc.0
    IL_0007: ldc.i4.s 10
    IL_0009: bne.un.s IL_0010

    IL_000b: ldloc.1
    IL_000c: ldc.i4.s 20
    IL_000e: pop
    IL_000f: pop

    IL_0010: ret
    } // end of method Test::Method2

method1 get 00:00:00.0000019 second for invoke.

method2 get 00:00:00.0000006 second for invoke.

I write this code for test

public class Program
    {
        private static void Main(string[] args)
        {
            var test = new Test();
            test.Method1();
            test.Method2();
            System.Console.ReadLine();
        }
    }


    public class Test
    {
        public void Method1()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var x = 10;
            var y = 20;
            if (x == 10)
            {
                if (y == 20)
                {

                }
            }
            stopwatch.Stop();

            Console.WriteLine("Time Method1: {0}",
                stopwatch.Elapsed);
        }

        public void Method2()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var x = 10;
            var y = 20;
            if (x == 10 && y == 20)
            {

            }
            stopwatch.Stop();
            Console.WriteLine("Time Method2: {0}",
                stopwatch.Elapsed);
        }
    }

I change the place of method1 and method2.

 test.Method2();
 test.Method1();

and re-run the test.

method1 get 00:00:00.0000006 second for invoke.

method2 get 00:00:00.0000019 second for invoke.

When I change the place of methods, the second method spends more time than the first method! What is the reason?

Upvotes: 3

Views: 165

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500525

You're timing a trivial amount of code, in such a way that any number of tiny incidental things will be disturbing the results - a page fault or cache miss could become relevant at that point... and that could easily be affected by the ordering of methods.

You should really benchmark multiple calls - or any way of doing enough work to take a reasonable amount of time. Any benchmark which measures time less than a second or so is dubious, IMO.

Additionally:

  • You almost certainly don't want to include JIT compilation time.
  • JIT compilation should be able to remove code which is basically pointless, most of the time. I typically add some sort of accumulator and output the result at the end of the test (after stopping the Stopwatch) to keep the JIT compiler "honest".

See Eric Lippert's benchmarking series for more details (and other pitfalls like GC):

Upvotes: 11

Related Questions