Why is n++ faster than n=n+1?
The answer is related to the old CISC cpu instructions and the way how C (or any programming language) is compiled to binary code.
In almost every CISC CPU there is a special “add” instruction that is named INC (or DEC) and that instruction increments (or decrements) by 1 the value of a register (or memory). If you use another instruction for addition you have to add both operands you want to sum. That makes INC/DEC more efficient: They take less space (no space for operands). In CISC they execute faster (because you save time to load operands).
The initial C compiler has been technically a simple 3 step macro processor on top of assembly so it was leaving this choice to the programmer.
You got this ++
instruction as a shortcut to the assembly INC. This is even written in the Kernigan’s book.
So ++
and —-
instructions are always more or equally efficient to any other form of summation.
They take less memory, sometimes are executed faster and they are even more compact in your source.
However, the modern compilers are pre-optimizing the binary code, so if your CPU supports INC instruction, even if you wrote n=n+1
, the compiler is going to convert it to INC (or n++
) and it will be as efficient as n++
.
Therefore, today, it doesn’t really matter much how you write it, at least for the compiled languages.
However, in the interpreted languages is always faster to write as minimum code / logic outside of the embedded functionality as possible. This leaves most of the work to efficient libraries and pre-compiled code, instead to the interpreter’s main loop.
So for example, if you do n=n+1
in such language, many of them will do as a minimum one additional memory copy and that will decrease the overall performance.
Even those, that do JIT are going to achieve the maximum efficiency only after several executions. Unless they pre-optimize the binary code (which increases the cost of the loading time).
As a result, n++
will be always be executed faster than n=n+1
.
$ time perl -le '$n=0; foreach (1..100000000) { $n++ }'
real 0m2.389s
user 0m2.371s
sys 0m0.015s
$ time perl -le '$n=0; foreach (1..100000000) { $n=$n+1 }'
real 0m4.469s
user 0m4.442s
sys 0m0.020s
As a general rule, it is not a good pattern for one to rely on the optimization engines of the compilers or interpreters.
Following the language pattern is always better.
Therefore, using n++
instead of n=n+1
is always beneficial:
faster or equal speed of execution smaller or equal in size binary code smaller or equal in size memory, stack, register usage more compact source code performance mobility (even if you recompile it on another place with compiler without optimizations, you are still going to gain) Some may argue that you lose readability, but this is questionable.