I want to know what variant from these two are faster:
if(a){
if(b){
//something here
}
}
or
if(a and b){
//something here
}
Thanks!
I want to know what variant from these two are faster:
if(a){
if(b){
//something here
}
}
or
if(a and b){
//something here
}
Thanks!
They will almost certainly compile to exactly the same code.
But, the more important question is: Why on earth do you care? Shaving one or two clock cycles will almost never make any difference whatsoever, and pursuing such microscopic optimizations is a complete waste of time and energy. It is exceedingly rarely that such optimization is in any way justified, and in those circumstances the better solution is to simply resort to assembly language.
Regards,
Ray L.
#2, though in the gran scheme of things it's not likely to matter much.
"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
-- Donald Knuth
This probably isn't part of that 3%.
It can't be the same code because of short circuiting. For the second, if a is false b is never evaluated and the branch not taken. For the second, both if's have to be evaluated.
Thanks for responses!
Why on earth do you care?
For my curiosity! ![]()
I think that is something interesting because It is met frequently.
KeithRB:
For the second, both if's have to be evaluated.
Nope. The whole construct (in this case the if) is skipped if a is false.
Ah! you are right.
I agree that putting a bunch of time and energy into optimizing before determining if it's even necessary is a bad idea but it's worth getting into some good coding habits that don't take much, if any, extra time or make the code harder to read/maintain. For example:
if (readFlag == true && analogRead(A0) > 200) {
instead of:
if (analogRead(A0) > 200 && readFlag == true) {
Takes very little extra effort and has the potential to make a big difference in the speed of your code. There is middle ground between not considering optimization at all and going overboard.
pert:
I agree that putting a bunch of time and energy into optimizing before determining if it's even necessary is a bad idea but it's worth getting into some good coding habits that don't take much, if any, extra time or make the code harder to read/maintain. For example:if (readFlag == true && analogRead(A0) > 200) {instead of:
if (analogRead(A0) > 200 && readFlag == true) {Takes very little extra effort and has the potential to make a big difference in the speed of your code. There is middle ground between not considering optimization at all and going overboard.
I still don't really understand why
if (readFlag == true && analogRead(A0) > 200) {
is better than
if (analogRead(A0) > 200 && readFlag == true) {
I know the coding order in C but not sure how the machine code in reallity. Can you explain more about the optimization?
They're evaluated in the order they're placed.
Evaluating this:-readFlag == truetakes very little time.
Evaluating this:-
analogRead(A0) > 200takes a little over 100us.
If the first is false, the second is not tested.
OldSteve:
They're evaluated in the order they're placed.
Evaluating this:-readFlag == truetakes very little time.Evaluating this:-
analogRead(A0) > 200takes a little over 100us.
If the first is false, the second is not tested.
It's worth noting that this is not accidental, it's part of the definition of the C++ language. It's also true of other languages like java, where you use constructs like
if(p != null && p.value < 10)
Another spot you'll see it is in unix shell scripts: for f in * ; do thing "$f" || echo "thing $f failed"; done
Relying on the "short circuiting' behaviour of the ||, &&, and ?: operators is a common programming idiom.
vlad2005:
I want to know what variant from these two are faster:
Compile both and extract the assembly code using avr-objdump.
C:\Users\sterretje\Documents\Arduino\Projects\Forums\test>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump.exe" -S sketch_sep20b.ino.elf > sketch_sep20b.ino.lst
Using IDE 1.6.7, both of your versions result in the same assembly code
void loop()
{
13a: cf 93 push r28
byte b1 = digitalRead(2);
13c: 82 e0 ldi r24, 0x02 ; 2
13e: 0e 94 14 01 call 0x228 ; 0x228 <digitalRead>
142: c8 2f mov r28, r24
byte b2 = digitalRead(3);
144: 83 e0 ldi r24, 0x03 ; 3
146: 0e 94 14 01 call 0x228 ; 0x228 <digitalRead>
if (b1)
14a: cc 23 and r28, r28
14c: 49 f0 breq .+18 ; 0x160 <loop+0x26>
{
if (b2)
14e: 88 23 and r24, r24
150: 39 f0 breq .+14 ; 0x160 <loop+0x26>
{
Serial.println("Both high");
152: 60 e0 ldi r22, 0x00 ; 0
154: 71 e0 ldi r23, 0x01 ; 1
156: 8c e2 ldi r24, 0x2C ; 44
158: 91 e0 ldi r25, 0x01 ; 1
}
}
}
15a: cf 91 pop r28
if (b1)
{
if (b2)
{
Serial.println("Both high");
15c: 0c 94 69 03 jmp 0x6d2 ; 0x6d2 <_ZN5Print7printlnEPKc>
}
}
}
160: cf 91 pop r28
162: 08 95 ret
void loop()
{
13a: cf 93 push r28
byte b1 = digitalRead(2);
13c: 82 e0 ldi r24, 0x02 ; 2
13e: 0e 94 14 01 call 0x228 ; 0x228 <digitalRead>
142: c8 2f mov r28, r24
byte b2 = digitalRead(3);
144: 83 e0 ldi r24, 0x03 ; 3
146: 0e 94 14 01 call 0x228 ; 0x228 <digitalRead>
if(b1 && b2)
14a: cc 23 and r28, r28
14c: 49 f0 breq .+18 ; 0x160 <loop+0x26>
14e: 88 23 and r24, r24
150: 39 f0 breq .+14 ; 0x160 <loop+0x26>
{
Serial.println("Both high");
152: 60 e0 ldi r22, 0x00 ; 0
154: 71 e0 ldi r23, 0x01 ; 1
156: 8c e2 ldi r24, 0x2C ; 44
158: 91 e0 ldi r25, 0x01 ; 1
}
}
15a: cf 91 pop r28
byte b1 = digitalRead(2);
byte b2 = digitalRead(3);
if(b1 && b2)
{
Serial.println("Both high");
15c: 0c 94 69 03 jmp 0x6d2 ; 0x6d2 <_ZN5Print7printlnEPKc>
}
}
160: cf 91 pop r28
162: 08 95 ret
Note
the elf files can be found in
C:\Users\yourusername\AppData\Local\Temp\buildXXX.tmp; observe the IDE's output window to see which temporary directory is used; e.g.
"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino5/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives [b]"C:\Users\sterretje\AppData\Local\Temp\build865386780d8ee6fd36497e86b1d5bdcf.tmp\[/b]preproc\ctags_target_for_gcc_minus_e.cpp"
A rationale for using two separate if would be if you want two separate else. Otherwise indeed it generates the same code