views:

210

answers:

5

is var x = new Stuff(); x.DoStuff();faster than new Stuff().DoStuff(); ?

I'm not sure why but I noticed in my code that the first method makes it faster, anybody knows which one is faster and why ?

+3  A: 

IMO the speed should be exactly the same for both versions. Maybe your benchmark is flawed?

ammoQ
+7  A: 

It seems that in this case you can make DoStuff a static method.

So rather then use

Stuff.DoStuff();

Have a look at

astander
+4  A: 

This is the IL code that they produce:

new Stuff().DoStuff();:

  // Code size       11 (0xb)
  .maxstack  8
  IL_0000:  newobj     instance void ConsoleApplication1.Stuff::.ctor()
  IL_0005:  call       instance void ConsoleApplication1.Stuff::DoStuff()
  IL_000a:  ret

var x = new Stuff(); x.DoStuff();:

  // Code size       13 (0xd)
  .maxstack  1
  .locals init ([0] class ConsoleApplication1.Stuff x)
  IL_0000:  newobj     instance void ConsoleApplication1.Stuff::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  callvirt   instance void ConsoleApplication1.Stuff::DoStuff()
  IL_000c:  ret

When iterating over the two variations 1000000 times, the new Stuff().DoStuff(); version uses around 20% less time. Nothing I would bother about (the difference was 0.8 ms on one million iterations).

Fredrik Mörk
Yeah I think if that miniscule amount of difference mattered to me, i wouldn't be using .NET in the first place
dan
+8  A: 

Actually the second should be faster as it performs fewer operations. Let's take this program for example:

class Program
{
    public void Foo() { }

    static void Main() 
    {}

    static void Method1()
    {
        var x = new Program();
        x.Foo();
    }

    static void Method2()
    {
        new Program().Foo();
    }
}

Here's how Method1 and Method2 look like when compiled in Release mode:

.method private hidebysig static void Method1() cil managed
{
    .maxstack 1
    .locals init (
        [0] class Program x)
    L_0000: newobj instance void Program::.ctor()
    L_0005: stloc.0 
    L_0006: ldloc.0 
    L_0007: callvirt instance void Program::Foo()
    L_000c: ret 
}

.method private hidebysig static void Method2() cil managed
{
    .maxstack 8
    L_0000: newobj instance void Program::.ctor()
    L_0005: call instance void Program::Foo()
    L_000a: ret 
}

Of course this sort of micro-optimization questions should never be asked.

Darin Dimitrov
Furthermore, the JIT compiler will probably create the same machine code out of that IL anyway.
Greg Hewgill
+1 for you: "Of course this sort of micro-optimization questions should never be asked." -1 for the question.
Andrew
Is that with all optimisations enables? I've seen the compiler remove variables on occasion, making them identical...
Marc Gravell
+1  A: 

The first version needs to store the reference to x in the locals, which the latter version doesn't, this cannot be done without consuming additional instructions. However, even the slightest change in the code will change the performance.

And please do not over-estimate the efficiency of the JIT'er, the JIT needs to balance speed of compilation with the efficiency of the code generated, the JIT'er is not the pen-ultimate application for generating machine code from CIL code.

Anton