9

i += a should be equivalent to i = i + a. In the case where a == 1, this is supposedly less efficient as ++i as it involves more accesses to memory; or will the compiler make it exactly the same as ++i?

Erwin Mayer
  • 18,076
  • 9
  • 88
  • 126
  • @paxdiablo: Brilliant. I'm going to help promote those posts of yours from now on. – BoltClock Jul 31 '11 at 13:08
  • Avoid premature optimization, you shouldn't be concerned by this. Your compiler is a *very* smart piece of code, learn to trust it for that kind of things and focus on the problem you want to solve. – Frédéric Hamidi Jul 31 '11 at 13:10
  • Similar question http://stackoverflow.com/questions/467322/is-there-any-performance-difference-between-i-and-i-in-c – Orhan Cinar Jul 31 '11 at 13:13
  • Thanks. I had seen the questions related to ++i and i++ but was wondering specifically on the difference with += 1 (as this operator can be use for incrementing with other values). – Erwin Mayer Jul 31 '11 at 13:17
  • Irrelevant and I'm sure it was asked before. Just hard to find. – H H Jul 31 '11 at 13:18
  • 1
    @Orhan, in this case, the purpose of asking instead of profiling is to seek an answer that is backed by some technical insight, and as general as possible in terms of good programming habits. – Erwin Mayer Jul 31 '11 at 13:19

5 Answers5

17

It is easy to answer: the C# compiler translates C# source code to IL opcodes. There is no dedicated IL opcode that performs the equivalent of the ++ operator. Which is easy to see if you look at the generated IL with the ildasm.exe tool. This sample C# snippet:

        int ix = 0;
        ix++;
        ix = ix + 1;

Generates:

  IL_0000:  ldc.i4.0               // load 0
  IL_0001:  stloc.0                // ix = 0

  IL_0002:  ldloc.0                // load ix
  IL_0003:  ldc.i4.1               // load 1
  IL_0004:  add                    // ix + 1
  IL_0005:  stloc.0                // ix = ix + 1

  IL_0006:  ldloc.0                // load ix
  IL_0007:  ldc.i4.1               // load 1
  IL_0008:  add                    // ix + 1
  IL_0009:  stloc.0                // ix = ix + 1

It generates the exact same code. Nothing the jitter can do but generate machine code that is equally fast.

The pre/post increment operator is syntax sugar in C#, use it wherever it makes your code more legible. Or perhaps more relevant: avoid it where it makes it less legible. They do have a knack for letting you create expressions that have too many side-effects.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
4

The compiler should optimise the code whichever way you write it so I believe i = i + 1 is the same as ++i.

Seth
  • 8,213
  • 14
  • 71
  • 103
2

I don't think there will be any difference, but You can put it in action, something like:

class Program
{
    static void Main(string[] args)
    {
        //Add values
        List<objClass> lst1 = new List<objClass>();
        for (int i = 0; i < 9000000; i++)
        {
            lst1.Add(new objClass("1", ""));
        }

        //For loop ++i
        DateTime startTime = DateTime.Now;
        for (int i = 0; i < 9000000; ++i)
        {
            lst1[i]._s1 = lst1[i]._s2;
        }
        Console.WriteLine((DateTime.Now - startTime).ToString());

        //For loop i+=1
        startTime = DateTime.Now;
        for (int i = 0; i < 9000000; i+=1)
        {
            lst1[i]._s1 = lst1[i]._s2;
        }
        Console.WriteLine((DateTime.Now - startTime).ToString());

    }
public class objClass
    {
        public string _s1 { get; set; }
        public string _s2 { get; set; }

        public objClass(string _s1, string _s2)
        {
            this._s1 = _s1;
            this._s2 = _s2;
        }
    }

}
Rami Alshareef
  • 7,015
  • 12
  • 47
  • 75
1

It depends. In theory, given a sufficiently naive compiler, ++x might well be more efficient than x += 1.

However, I don't know of such a naive compiler.

  • if the value of the operand is known at compile-time, then the compiler can optimize the operation.
  • if the value can be determined to be constant at run-time, then JIT compiler can optimize the operation as well.

Moreover, modern CPUs are highly complex beasts, which can execute a lot of operations in parallel, and quite often, "simple" operations like these can be entirely hidden by running them in parallel with larger, more complex ones.

A good rule of thumb, when optimizing and just when writing in general is to express your intent as clearly as possible.

That makes it easier for other programmers to read your code, but it also makes it easier for the compiler to do so.

If you want to increment a value, use the increment operator (++), because it describes exactly what you want to do.

If you want to add a variable or unknown value, use the += operator, because that is what it's for.

If you're clear about your intentions, then the compiler gets more information about your code, and can optimize accordingly.

If you write x += 1, you're really trying to trip up the compiler. You're saying "use the general-purpose addition operator to add one to x". Then the compiler has to figure out "ok, you said to use general-purpose addition, but I can see that's nto necessary, so I'm just going to increment instead". You could have told it that. Now, instead, you have to rely on the compiler being clever.

jalf
  • 243,077
  • 51
  • 345
  • 550
0

Unless a is defined a const int == 1 how can the compiler know at compile time that a == 1?

So the answer must be no, the compiler cannot compile this to ++i.

James Gaunt
  • 14,631
  • 2
  • 39
  • 57
  • The compiler can know because a: it is invoked as `i += 1`, that is, with a literal 1 on the rhs, in which case the compiler can trivially inline it, or b: because C# is JIT-compiled, so if at runtime, the JIT can determine that the parameter is 1, it can optimize the operation accordingly. So the answer "must" certainly not be no. It might be, but it doesn't *have* to be. – jalf Jul 31 '11 at 13:09
  • a is a variable, the JITter cannot know its value at compile time or JIT time unless it is a constant. Perhaps we are reading this question differently. I am thinking now the title and the body of the question aren't actually asking the same thing. – James Gaunt Jul 31 '11 at 13:10
  • in the case a is a variable it is true that there is no way the compiler can optimize the code beforehand. My question was more when a is a literal (that is, written as "1"). – Erwin Mayer Jul 31 '11 at 13:13
  • 1
    Nitpicking: A (tracing) JIT-compiler could actually optimize based on some value found at runtime and add a guard to break out if the value changes. They just choose not to for normal variables because those are, well, variable and thus likely to invalidate the trace quickly. Not that it matters for this question, in practice, or even if it actually happened. –  Jul 31 '11 at 13:15
  • @James: it can certainly know the value at JIT time. it might be able to deduce that even though the variable isn't declared `const`, it will always have the value `1` here, and so it can be optimized. And of course, if you don't know that the operand is 1, then it makes no sense to compare `++` and `+=` – jalf Jul 31 '11 at 13:15
  • Ok ok... given a suitably clever compiler and suitable code it's possible to deduce... I was just answering the question as written however - not the title of the question. – James Gaunt Jul 31 '11 at 13:17