Chad
Chad

Reputation: 24679

x=x+1 vs. x +=1

I'm under the impression that these two commands result in the same end, namely incrementing X by 1 but that the latter is probably more efficient.

If this is not correct, please explain the diff.

If it is correct, why should the latter be more efficient? Shouldn't they both compile to the same IL?

Thanks.

Upvotes: 32

Views: 27628

Answers (17)

Mike Dunlavey
Mike Dunlavey

Reputation: 40649

If x is a simple integer scalar variable, they should be the same.

If x is a large expression, possibly with side effects, +=1 and ++ should be twice as fast.

Many people concentrate on this kind of low-level optimization as if that's what optimization is all about. I assume you know it's a much bigger subject.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533442

Something worth noting is that +=, -=, *= etc. do an implicit cast.

int i = 0;
i = i + 5.5; // doesn't compile.
i += 5.5; // compiles.

Upvotes: 1

Mehrdad Afshari
Mehrdad Afshari

Reputation: 421968

IMPORTANT:

The answers specifying evaluation are certainly correct in terms of what a += do, in general languages. But in VB.NET, I assume X specified in the OP is a variable or a property.


They'll probably compile to the same IL.

UPDATE (to address the probably controversy):

VB.NET is a specification of a programming language. Any compiler that conforms to what's defined in the spec can be a VB.NET implementation. If you edit the source code of the MS VB.NET compiler to generate crappy code for X += 1 case, you'll still conform to VB.NET spec (because it didn't say anything about how it's going to work. It just says the effect will be exactly the same, which makes it logical to generate the same code, indeed).

While the compiler is very very likely (and I feel it really does) generate the same code for both, but it's pretty complex piece of software. Heck, you can't even guarantee that a compiler generates the exact same code when the same code is compiled twice!

What you can feel 100% secure to say (unless you know the source code of the compiler intimately) is that a good compiler should generate the same code, performance-wise, which might or might not be the exact same code.

Upvotes: 11

CoderDennis
CoderDennis

Reputation: 13837

From the MSDN library for +=:

Using this operator is almost the same as specifying result = result + expression, except that result is only evaluated once.

So they are not identical and that is why x += 1 will be more efficient.

Update: I just noticed that my MSDN Library link was to the JScript page instead of the VB page, which does not contain the same quote.

Therefore upon further research and testing, that answer does not apply to VB.NET. I was wrong. Here is a sample console app:

Module Module1

Sub Main()
    Dim x = 0
    Console.WriteLine(PlusEqual1(x))
    Console.WriteLine(Add1(x))
    Console.WriteLine(PlusEqual2(x))
    Console.WriteLine(Add2(x))
    Console.ReadLine()
End Sub

Public Function PlusEqual1(ByVal x As Integer) As Integer
    x += 1
    Return x
End Function

Public Function Add1(ByVal x As Integer) As Integer
    x = x + 1
    Return x
End Function

Public Function PlusEqual2(ByVal x As Integer) As Integer
    x += 2
    Return x
End Function

Public Function Add2(ByVal x As Integer) As Integer
    x = x + 2
    Return x
End Function

End Module

IL for both PlusEqual1 and Add1 are indeed identical:

.method public static int32 Add1(int32 x) cil managed
{
.maxstack 2
.locals init (
    [0] int32 Add1)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.1 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

The IL for PlusEqual2 and Add2 are nearly identical to that as well:

.method public static int32 Add2(int32 x) cil managed
{ 
.maxstack 2
.locals init (
    [0] int32 Add2)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.2 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

Upvotes: 111

xenodevil
xenodevil

Reputation: 604

i thought the differences are due to the additional clock cycles used for memory references, but i turned out to be wrong! can't understand this thing myself

instruction type        example                      cycles

===================================================================

ADD reg,reg             add ax,bx                       1
ADD mem,reg             add total, cx                   3
ADD reg,mem             add cx,incr                     2
ADD reg,immed           add bx,6                        1
ADD mem,immed           add pointers[bx][si],6          3
ADD accum,immed         add ax,10                       1

INC reg                 inc bx                          1
INC mem                 inc vpage                       3

MOV reg,reg             mov bp,sp                       1
MOV mem,reg             mov array[di],bx                1
MOV reg,mem             mov bx,pointer                  1
MOV mem,immed           mov [bx],15                     1
MOV reg,immed           mov cx,256                      1
MOV mem,accum           mov total,ax                    1
MOV accum,mem           mov al,string                   1
MOV segreg,reg16        mov ds,ax                       2, 3
MOV segreg,mem16        mov es,psp                      2, 3
MOV reg16,segreg        mov ax,ds                       1
MOV mem16,segreg        mov stack_save,ss               1
MOV reg32,controlreg    mov eax,cr0                     22
                        mov eax,cr2                     12
                        mov eax,cr3                     21, 46
                        mov eax,cr4                     14
MOV controlreg,reg32    mov cr0,eax                     4
MOV reg32,debugreg      mov edx,dr0                     DR0-DR3,DR6,DR7=11;
                                                        DR4,DR5=12 
MOV debugreg,reg32      mov dr0,ecx                     DR0-DR3,DR6,DR7=11;
                                                        DR4,DR5=12 

source:http://turkish_rational.tripod.com/trdos/pentium.txt

the instructions may be tranlated as:

;for i = i+1   ; cycles
mov  ax,   [i]  ; 1
add  ax,   1    ; 1
mov  [i],  ax   ; 1

;for i += 1
; dunno the syntax of instruction. it should be the pointers one :S     

;for i++
inc  i          ; 3
;or
mov  ax,   [i]  ; 1
inc  ax         ; 1
mov  [i],  ax   ; 1

;for ++i
mov  ax,   [i]  ; 1
;do  stuff      ; matters not
inc  ax         ; 1
mov  [i],  ax   ; 1

all turn out to be same :S its just some data that may be helpful. please comment!

Upvotes: 1

Milan Babuškov
Milan Babuškov

Reputation: 61098

In C++ it depends what datatype is x and how are operators defined. If x is an instance of some class you can get completely different results.

Or maybe you should fix the question and specify that x is an integer or whatever.

Upvotes: 1

BlackStar
BlackStar

Reputation:

So many speculations! Even the conclusion with the Reflector thingy is not necessarily true because it can do optimizations while dissassembling.

So why does none of you guys just have a look into the IL code? Have a look at the following C# programme:

static void Main(string[] args)
{
    int x = 2;
    int y = 3;
    x += 1;
    y = y + 1;
    Console.WriteLine(x);
    Console.WriteLine(y);
}

This code snippet compiles to:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
// some commands omitted here

IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0

IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1

// some commands omitted here
}

As you can see, it's in fact absolutely the same. And why is it? Because IL's purpose is to tell what to do, not how to. The optimization will be a job of the JIT compiler. Btw it's the same in VB.Net

Upvotes: 8

Vinicius Rocha
Vinicius Rocha

Reputation: 4223

I wrote a simple console app:

static void Main(string[] args)
{
    int i = 0;
    i += 1;
    i = i + 1;
    Console.WriteLine(i);
}

I disassembled it using Reflector and here's what i got:

private static void Main(string[] args)
{
    int i = 0;
    i++;
    i++;
    Console.WriteLine(i);
}

They are the same.

Upvotes: 26

Paul Sonier
Paul Sonier

Reputation: 39480

They may be the same in VB; they are not necessarily the same in C (where the operator comes from).

Upvotes: 2

Paul Tomblin
Paul Tomblin

Reputation: 182762

Back in the early 1980s, one of the really cool optimizations of the Lattice C Compiler was that "x = x + 1;", "x += 1;" and "x++;" all produced exactly the same machine code. If they could do it, a compiler written in this millenium should definitely be able to do it.

Upvotes: 0

Drew Hoskins
Drew Hoskins

Reputation: 4186

On x86, if x is in register eax, they will both result in something like

inc eax;

So you're right, after some compilation stage, the IL will be the same.

There's a whole class of questions like this that can be answered with "trust your optimizer."

The famous myth is that
x++;
is less efficient than
++x;
because it has to store a temporary value. If you never use the temporary value, the optimizer will remove that store.

Upvotes: 4

Luixv
Luixv

Reputation: 8710

are the same.

x=x+1 

is mathematical seen a contradiction whereas

x+=1

isn't and is light to be typed.

Upvotes: 2

Andrew Ensley
Andrew Ensley

Reputation: 11697

There is no difference in programmatic efficiency; just typing efficiency.

Upvotes: 0

Macke
Macke

Reputation: 25680

The optimizer probably produces the same result, if x is a simple type like int or float.

If you'd use some other language (limited VB knowledge here, can you overload +=?) where x could be one big honking object, the former creates and extra copy, which can be hundreds of megs. The latter does not.

Upvotes: 2

Greg D
Greg D

Reputation: 44066

  1. Yes, they behave the same.
  2. No, they are probably equally efficient. Optimizers are good at that sort of thing. If you'd like to double check, write the optimized code and view it in reflector.

Upvotes: 2

Brian
Brian

Reputation: 8357

At run time (at least with PERL) there is no difference. x+=1 is roughly .5 seconds faster to type than x = x+1 though

Upvotes: 0

z  -
z -

Reputation: 7168

they compile to the same, the second is just easier to type.

Upvotes: 18

Related Questions