简体   繁体   中英

if statement inside a loop or vice versa

I'm wondering which is more efficient.

Let's say I have this code:

while (i<10000){
   if (cond1)
      doSomething1();
   else if (cond2)
      doSomething2();
   else
      doSomething3();
}

Now cond1 and cond2 are "constant" conditions, which means that if it happens once for i it will happen to all of them, and just one of them can be true. Most of the time, the last doSomething3() is executed.

Now what happens if I write something like this:

if (cond1){
   while (i<10000)
      doSomething1();
}
else if (cond2){
   while (i<10000)
      doSomething2();
}
else{
   while (i<10000)
      doSomething3();
}

Is it more efficient because I'm checking cond1 and cond2 just once?

What you need to be asking is which is more cache-efficient.

In many cases, the compiler can figure this out for you and will rearrange your code to get the best results . Its ability to do so will depend largely on what doSomethingN does and what condN are. If condN can change over time, then it may well need to be physically checked each time, in which case your code cannot be substantially re-arranged and checking it on every loop iteration may indeed be far slower. But, if condN is constant, the repeated checks can be optimised away, essentially resulting in your first code being converted into the second.

Ultimately, the only way to be sure is to measure it (and study the resulting assembly, if you can understand it).

I think you've answered your own question. Yes, it's more efficient if you write more efficient code.

EDIT @NeilKirk has a point. Since your compiler knows what it's doing, manually checking outside is only at least as efficient, not necessarily more efficient, if the compiler can detect that the condition won't change during your loop.

On a first look, the second one looks like it is more efficient, after all one check is obviously more efficient than 10000 checks, well, more efficient performance wise, slightly more code is the price it comes at.

But then again, the performance overhead of the first one may very well be negligible, you should really benchmark the two, because you know, you don't have a performance problem until you prove you do.

At any rate, any production grade compiler will likely be able to optimize things for you in that fairly static and easy to analyze context.

It could be another scenario, where there are a lot more options, which might not be able to predict during compile time. For example you can have a hash map of conditions and function pointers, so you lookup the function pointer for the condition and use it to invoke the functionality. Naturally, this will be far less efficient, because it will use dynamic dispatch, which also means the calls cannot be inlined, but it is the price you pay for having it more flexible, for example using this approach you can register different functions and conditions during the runtime, you can change functionality for a given condition and whatnot.

For example consider a scenario where you need to perform 10000 actions, but each actions should depend on the result from the previous one.

while (i < 10000) cond = map[cond]();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM