0

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 ?

Omu
  • 69,856
  • 92
  • 277
  • 407
  • 3
    I'm pretty sure it's doing the same thing in the compiler anyway. Have you compared the IL for both? –  Dec 15 '09 at 08:21
  • 1
    How did you measure it? I think it is quite hard to measure such a small piece of code. You'd better optimize the DoStuff method, and only if it is a really bottleneck. – jmservera Dec 15 '09 at 08:30
  • 1
    From such a terse code example, with no indication of how things are declared, I fail to see how any reasonable benchmarks could be designed. By the way I didn't down-vote this. Please consider making the question a little more elaborated, and the code sample more explicit. – BillW Dec 15 '09 at 08:36
  • +1: Although it's true that you should not do this kind of micro-optimization in your code, your question (and the answers) are interesting from a theoretical point of view. – Heinzi Dec 15 '09 at 17:22

5 Answers5

9

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.

Chris Cudmore
  • 29,793
  • 12
  • 57
  • 94
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 5
    Furthermore, the JIT compiler will probably create the same machine code out of that IL anyway. – Greg Hewgill Dec 15 '09 at 08:32
  • 2
    +1 for you: "Of course this sort of micro-optimization questions should never be asked." -1 for the question. – Andrew Dec 15 '09 at 08:45
  • 1
    Is that with all optimisations enables? I've seen the compiler remove variables on occasion, making them identical... – Marc Gravell Dec 15 '09 at 12:12
7

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

So rather then use

Stuff.DoStuff();

Have a look at

Community
  • 1
  • 1
Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
4

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
  • 155,851
  • 29
  • 291
  • 343
  • 4
    Yeah I think if that miniscule amount of difference mattered to me, i wouldn't be using .NET in the first place – dan Dec 15 '09 at 08:41
3

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

Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
1

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
  • 488
  • 4
  • 15