I have heard a teacher drop this once, and it has been bugging me ever since. Let's say we want to check if the integer x
is bigger than or equal to 0. There are two ways to check this:
if (x > -1){
//do stuff
}
and
if (x >= 0){
//do stuff
}
According to this teacher >
would be slightly faster then >=
. In this case it was Java, but according to him this also applied for C, c++ and other languages. Is there any truth to this statement?
">=" is single operation, just like ">". Not 2 separate operations with OR.
But >=0 is probably faster, because computer need to check only one bit (negative sign).
There's no difference in any real-world sense.
Let's take a look at some code generated by various compilers for various targets.
-O2
for GCC,/Ox
for MSVC,-Oh
for IAR)using the following module:
And here's what each of them produced for the comparison operations:
MSVC 11 targeting ARM:
MSVC 11 targeting x64:
MSVC 11 targeting x86:
GCC 4.6.1 targeting x64
GCC 4.6.1 targeting x86:
GCC 4.4.1 targeting ARM:
IAR 5.20 targeting an ARM Cortex-M3:
If you're still with me, here are the differences of any note between evaluating
(x > -1)
and(x >= 0)
that show up:cmp r0,#0xFFFFFFFF
for(x > -1)
vscmp r0,#0
for(x >= 0)
. The first instruction's opcode is two bytes longer. I suppose that may introduce some additional time, so we'll call this an advantage for(x >= 0)
cmp ecx, -1
for(x > -1)
vstest ecx, ecx
for(x >= 0)
. The first instruction's opcode is one byte longer. I suppose that may introduce some additional time, so we'll call this an advantage for(x >= 0)
Note that GCC and IAR generated identical machine code for the two kinds of comparison (with the possible exception of which register was used). So according to this survey, it appears that
(x >= 0)
has an ever-so-slight chance of being 'faster'. But whatever advantage the minimally shorter opcode byte encoding might have (and I stress might have) will be certainly completely overshadowed by other factors.I'd be surprised if you found anything different for the jitted output of Java or C#. I doubt you'd find any difference of note even for a very small target like an 8 bit AVR.
In short, don't worry about this micro-optimization. I think my write up here has already spent more time than will be spent by any difference in the performance of these expressions accumulated across all the CPUs executing them in my lifetime. If you have the capability to measure the difference in performance, please apply your efforts to something more important like studying the behavior of sub-atomic particles or something.
In fact I believe the second version should be slightly faster as it requires a single bit check(assuming you compare at zero as you show above). However such optimizations never really show as most compilers will optimize such calls.
A bigger concern here is premature optimisation. Many consider writing readable code more important than writing efficient code [1, 2]. I would apply these optimisations as a last stage in a low level library once the design has been proven to work.
You shouldn't be constantly considering making minuscule optimisations in your code at the cost of readability, since it'll make reading and maintaing the code harder. If these optimisations need to take place, abstract them into lower level functions so you're still left with code that's easier to read for humans.
As a crazy example, consider someone who writes their programs in assembly to someone who's willing to forgo that extra efficiency and use Java for its benefits in design, ease of use and maintainability.
As a side note, if you're using C, perhaps writing a macro which uses the slightly more efficient code is a more feasible solution, since it will achieve efficiency, readability and maintainability more than scattered operations.
And of course the tradeoffs of efficiency and readability depend on your application. If that loop is running 10000 times a second then it's a possibly bottleneck and you may want to invest time in optimising it, but if it's a single statement that's called occasionally it's probably not worth it for the minute gain.
It is very much dependent on the underlying architecture, but any difference will be minuscule.
If anything, I'd expect
(x >= 0)
to be slightly faster, as comparison with0
comes for free on some instruction sets (such as ARM).Of course, any sensible compiler will choose the best implementation regardless of which variant is in your source.
Your teacher is fundamentally wrong. Not only why chance are than comparing with 0 can be sligly fast, but because this sort of local optimization are well done by your compiler / interpreter, and you can mess all trying to help. Definitively not a good thing to teach.
You can read: this or this