0

So, I was marking a C++ test while our senior programmer was away and the very first question was something like this:

Without compiler optimizations, which method will run faster?

Method 1

for(int i = 0; i < 100000; i++) { }

Method 2

for(int i = 100000; i >= 0; --i) { }

Now, If you're like me and almost every other developer I've encountered (save now for one), you've been led to believe that pre-increment & pre-decrement operators (++i and --i) are inherently slower than post-increment & post-decrement operators. So naturally I went with Method 2.

However, our senior programmer returns and tells me that the two functions will run in equal time.

Thinking it was all some elaborate joke, I set out to prove him wrong and whipped this up:

#define ITERATIONS  (1000000000)
clock_t start = clock();
for(int64_t i = 0; i < ITERATIONS; i++)
{}
auto first_clock = clock() - start;

start = clock();
for(int64_t j = ITERATIONS; j > 0; --j)
{}
auto last_clock = clock() - start;

Much to my surprise:

first_clock = 25333
last_clock =  25277

For all intents and purposes, these methods are equal!

So, where did this myth come from? Was it true at one time and became false in newer compilers? Looking forward to an interesting discussion. :)

Community
  • 1
  • 1
Colin Basnett
  • 4,052
  • 2
  • 30
  • 49
  • 1
    Didn't you want to compare with `i++`?? – πάντα ῥεῖ Aug 26 '13 at 20:10
  • 5
    I'm severely disappointed your compiler didn't outright throw away *both* loops. – WhozCraig Aug 26 '13 at 20:11
  • @g-makulik copy paste error, fixed – Colin Basnett Aug 26 '13 at 20:12
  • 2
    There is a performance difference if used with other types, e.g. with some kind of `big_integer`. For that reason, it's a idiom in C++ to prefer pre-increments. – nosid Aug 26 '13 at 20:12
  • 2
    The speed difference isn't with integers, it is with iterators. – IdeaHat Aug 26 '13 at 20:13
  • @WhozCraig Running in debug mode, so no optimizations. – Colin Basnett Aug 26 '13 at 20:16
  • 3
    IMHO, you should take a look into assembly code generated in the case you really wanna know what is happening and which one is faster. Measuring the performance is not the right way, cause some compiler optimization or even another process can influence the results. – Hugo Corrá Aug 26 '13 at 20:19
  • @cmbasnett then [level the playing field](http://ideone.com/W67iOv). – WhozCraig Aug 26 '13 at 20:21
  • @nosid and MadScienceDreams: Even with other types and iterators, a halfway decent compiler will see that you aren't using the temporary and get rid of it making the performance difference between the two operators virtually nil. You should use the operator that makes sense for what you are doing. – Zac Howland Aug 26 '13 at 20:22
  • 5
    On many processors (*with* optimisations), comparison with zero may be faster than with an arbitrary value; the comparison can be combined with the decrement. Post vs. pre-increment won't make a jot of difference here, and there's no way to reason about the speed of unoptimised code. – Mike Seymour Aug 26 '13 at 20:23
  • @cmbasnett please replace 'slower' by 'faster' in 'you've been led to believe that pre-increment & pre-decrement operators (++i and --i) are inherently slower than post-increment & post-decrement operators. So naturally I went with Method 2.' –  Aug 26 '13 at 20:31
  • 2
    @WhozCraig Post/pre doesn't matter, and is probably there precisely to throw people into thinking that's what the question is about. Infact, it's about testing vs a non-zero value for end-of-loop vs testing against a sign change. It's an interview question, and designed to show how closely a programmer scrutinizes the question. – kfsone Aug 26 '13 at 20:35
  • @ZacHowland: It really depends on the compiler. Clang 3.4 succeeds to eliminate the temporary in some situations, but GCC 4.8 almost never succeeds. – nosid Aug 26 '13 at 20:36
  • @kfsone A good question then, because with everyone playing by the same constrictions (both/neither testing for zero, etc), the results are fairly obvious. Sounds like the voice of experience on your side. Gotta jot this one down for my iview file. – WhozCraig Aug 26 '13 at 20:40
  • 1
    following up on kfsone, examine a few instruction sets, one/some have a decrement and jump if zero, one instruction. Many have math operators (add/subtract) that change the flags, and there is a zero flag so you can do a subtract followed by a jump if zero, where counting up you increment compare with some number then jump if greater than or equal or zero or whatever and that compare may involve a loading of a register with that constant costing another instruction/time. So for some instruction sets there is no real difference, but on others there is a difference. – old_timer Aug 27 '13 at 00:30
  • Pre-increment is generally faster on non-integral data types (e.g. `std::vector <...>::iterator`). Beyond that, I have never seen any performance advantage on integral (i.e. `int`) data types. – Andon M. Coleman Aug 27 '13 at 05:46
  • C++ question not a dupe of C question. – Oktalist Nov 20 '14 at 14:54

0 Answers0