views:

630

answers:

10

I just want to know what the difference between all the conditional statements in objective-c and which one is faster and lighter.

+13  A: 

One piece of advice: stop worrying about which language constructs are microscopically faster or slower than which others, and instead focus on which ones let you express yourself best.

Ned Batchelder
There is nothing wrong with worrying, where do you think embedded, system, database, CPU designers and compiler writers come from ? Some people find this stuff interesting. Oh, and he did have iphone in his tag so there is battery life to be gained by micro-optimizing.
Hassan Syed
I hope this doesn't sound obnoxious, but someone who is asking about the difference between `if` and `while` should not be worrying about the relative performance of each. It's pretty clear that we are not dealing with someone micro-optimizing an embedded system. It is way too early for the OP to be thinking about the performance of these constructs.
Ned Batchelder
@Ned: This is a great answer. To how many questions are you getting upvotes for the same answer? :-)
Norman Ramsey
+1  A: 

while isn't a conditional it is a loop. The difference being that the body of a while-loop can be executed many times, the body of a conditional will only be executed once or not at all.

The difference between if and switch is that if accepts an arbitrary expression as the condition and switch just takes values to compare against. Basically if you have a construct like if(x==0) {} else if(x==1) {} else if(x==2) ..., it can be written much more concisely (and effectively) by using switch.

sepp2k
+1  A: 

A case statement could be written as

if (a)
{
    // Do something
}
else if (b)
{
    // Do something else
}

But the case is much more efficient, since it only evaluates the conditional once and then branches.

while is only useful if you want a condition to be evaluated, and the associated code block executed, multiple times. If you expect a condition to only occur once, then it's equivalent to if. A more apt comparison is that while is a more generalized for.

Tim Keating
Is that so? I heard switches were less efficient. How can a switch only be evaluated once? I'm pretty sure that behind the scenes it still has to compare to each case...
Mark
@Mark: don't listen - measure. The controlling expression of a switch may only be evaluated once. There are a variety of strategies available to the compiler for how to implement the jump to the correct piece of code. The worst and least efficient, in general, is to compare the computed values with the case alternatives. However, if the case values are sufficiently diverse and sparse, that may be the best way to deal with it. If the values are compact and dense (e.g. each alternative in the range 0..15), then a jump table can be used instead, indexed by the switch value.
Jonathan Leffler
@Jonathan: Oh! Now that's a clever optimization. Wish I could give you +rep.
Mark
@Jonathan: Yes, "evaluates once and branches" is a gross oversimplification. Thanks!@Mark: You can mark the comment as useful... not sure that gives rep but it makes the comment more visible.
Tim Keating
+9  A: 

If and case statements described

While statement described

Since these statements do different things, it is unproductive to debate which is faster.

It's like asking whether a hammer is faster than a screwdriver.

Shmoopty
(-1)There are actually subtleties involved in specifying branching constructs and loops. Just because you can't see it does not mean you need to ridicule the guy. Your links are also very high level and uninformative.
Hassan Syed
I intend no ridicule. My links are as high-level as the question, to the best of my judgment.
Shmoopty
I didn't read any ridicule into that... it's a valid and informative analogy.
Mark
A: 

loops and branches are hard to explain briefly, to get the best code out of a construct in any c-style language depends on the processor used and the local context of the code. The main objective is to reduce the breaking of the execution pipeline -- primarily by reducing branch mispredictions.

I suggest you go here for all your optimization needs. The manuals are written for the c-style programmer and relatively easy to understand if you know some assembly. These manuals should explain to you the subtleties in modern processors, the strategies used by top compilers, and the best way to structure code to get the most out of it.

Hassan Syed
What is up with you spam-downvoting every answer in this thread?
phoebus
every ? I upvoted two based on the merits of the content.
Hassan Syed
+1  A: 

Each condition statement serves a different purpose and you won't use the same one in every situation. Learn which ones are appropriate for which situation and then write your code. If you profile your code and find there's a bottleneck, then you go ahead and address it. Don't worry about optimizing before there's actually a problem.

(+1) for the general advice. However its very hard to find places where micro-optimization could have made a difference, the data is all statistical and mostly ( I suspect always actually) profilers cannot time these sub-optimal spots. A little knowledge before-hand goes a long way.
Hassan Syed
A: 

There are conditional statements and conditional loops. (If Wikipedia is to be trusted, then simply referring to "a conditional" in programming doesn't cover conditional loops. But this is a minor terminology issue.)

Shmoopty said "Since these statements do different things, it is nonsensical to debate which is faster."

Well... it may be time poorly spent, but it's not nonsensical. For instance, let's say you have an if statement:

if (cond) {
    code
}

You can transform that into a loop that executes at most one time:

while (cond) {
    code
    break;
}

The latter will be slower in pretty much any language (or the same speed, because the optimizer turned it back into the original if behind the scenes!) Still, there are occasions in computer programming where (due to bizarre circumstances) the convoluted thing runs faster

But those incidents are few and far between. The focus should be on your code--what makes it clearest, and what captures your intent.

Hostile Fork
(-1) a reply focusing on a single >>possible<< code transformation. He is asking for general information not surface level stuff that is google-able.
Hassan Syed
Love the gravatar :-)
paxdiablo
+5  A: 

The language-agnostic version (mostly, obviously this doesn't count for declarative languages or other weird ones):

When I was taught programming (quite a while ago, I'll freely admit), a language consisted of three ways of executing instructions:

  • sequence (doing things in order).
  • selection (doing one of many things).
  • iteration (doing something zero or more times).

The if and case statements are both variants on selection. If is used to select one of two different options based on a condition (using pseudo-code):

if condition:
    do option 1
else:
    do option 2

keeping in mind that the else may not be needed in which case it's effectively else do nothing. Also remember that option 1 or 2 may also consist of any of the statement types, including more if statements (called nesting).

Case is slightly different - it's generally meant for more than two choices like when you want to do different things based on a character:

select ch:
    case 'a','e','i','o','u':
        print "is a vowel"
    case 'y':
        print "never quite sure"
    default:
        print "is a consonant"

Note that you can use case for two options (or even one) but it's a bit like killing a fly with a thermonuclear warhead.

While is not a selection variant but an iteration one. It belongs with the likes of for, repeat, until and a host of other possibilities.

As to which is fastest, it doesn't matter in the vast majority of cases. The compiler writers know far more than we mortal folk how to get the last bit of performance out of their code. You either trust them to do their job right or you hand-code it in assembly yourself (I'd prefer the former).

You'll get far more performance by concentrating on the macro view rather than the minor things. That includes selection of appropriate algorithms, profiling, and targeting of hot spots. It does little good to find something that take five minutes each month and get that running in two minutes. Better to get a smaller improvement in something happening every minute.

The language constructs like if, while, case and so on will already be as fast as they can be since they're used heavily and are relative simple. You should be first writing your code for readability and only worrying about performance when it becomes an issue (see YAGNI).

Even if you found that using if/goto combinations instead of case allowed you to run a bit faster, the resulting morass of source code would be harder to maintain down the track.

paxdiablo
If you're doing that `switch()` statement in C, don't forget your `break;` statements.
Dave DeLong
The great thing about pseudo-code is that you can change what it means even after it's written :-)
paxdiablo
A: 

I just remembered the most important thing about conditionals and branching code. Order your code as follows

if(x==1); //80% of the time
else if(x==2); // 10% of the time
else if(x==3); //6% of the time
else break;

You must use an else sequence... and in this case the prediction logic in your CPU will predict correctly for x==1 and avoid the breaking of your pipeline for 80% of all execution.

More information from intel. Particularly:

In order to effectively write your code to take advantage of these rules, when writing if-else or switch statements, check the most common cases first and work progressively down to the least common. Loops do not necessarily require any special ordering of code for static branch prediction, as only the condition of the loop iterator is normally used.

By following this rule you are flat-out giving the CPU hints about how to bias its prediction logic towards your chained conditionals.

Hassan Syed
Hassan, the question is titled "What is the difference between an IF, CASE, and WHILE statement". It's a short question and I guess we can all read into that a level of experience we want to read into it. But I think the most logical way to interpret it is as a question a <i>very</i> new programmer would ask. An article from Intel about ("Branch and Loop Reorganization to Prevent Mispredicts") is probably going to be over their head.
Hostile Fork
"which one is faster and lighter": There is no simple answer to this, and it is the crux of his question -- there are only references to the material which will help him understand. If you look at his set of questions you would realize that he isn't that green.
Hassan Syed
Doesn't explain the difference between if, case and while.
Chuck
+1  A: 

Are you asking whether an if structure will execute faster than a switch statement inside of a large loop? If so, I put together a quick test, this code was put into the viewDidLoad method of a new view based project I just created in the latest Xcode and iPhone SDK:

NSLog(@"Begin loop");
NSDate *loopBegin = [NSDate date];

int ctr0, ctr1, ctr2, ctr3, moddedNumber;
ctr0 = 0;
ctr1 = 0;
ctr2 = 0;
ctr3 = 0;
for (int i = 0; i < 10000000; i++) {
 moddedNumber = i % 4;

 // 3.34, 1.23s in simulator
 if (moddedNumber == 0)
 {
  ctr0++;
 }
 else if (moddedNumber == 1)
 {
  ctr1++;
 }
 else if (moddedNumber == 2)
 {
  ctr2++;
 }
 else if (moddedNumber == 3)
 {
  ctr3++;
 }

 // 4.11, 1.34s on iPod Touch
 /*switch (moddedNumber)
 {
  case 0:
   ctr0++;
   break;
  case 1:
   ctr1++;
   break;
  case 2:
   ctr2++;
   break;
  case 3:
   ctr3++;
   break;
 }*/
}

NSTimeInterval elapsed = [[NSDate date] timeIntervalSinceDate:loopBegin];

NSLog(@"End loop: %f seconds", elapsed );

This code sample is by no means complete, because as pointed out earlier if you have a situation that comes up more times than the others, you would of course want to put that one up front to reduce the total number of comparisons. It does show that the if structure would execute a bit faster in a situation where the decisions are more or less equally divided among the branches.

Also, keep in mind that the results of this little test varied widely in performance between running it on a device vs. running it in the emulator. The times cited in the code comments are running on an actual device. (The first time shown is the time to run the loop the first time the code was run, and the second number was the time when running the same code again without rebuilding.)

BP