Arnold Zahrneinder
Arnold Zahrneinder

Reputation: 5200

The potential impact of an if statement inside a loop

Assuming we have the Boolean check = false, and the value for this variable is either always true or false meaning it never changes through the loop, would the following be more computationally efficient than the latter one?

First:

// The value of check variable never changes inside the loop.
if(check){
   for(int i=0; i < array.Length; i++){
       sb.Append(String.Format("\"{0}\"", array[i].ToString());
   }
}
else{
   for(int i=0; i < array.Length; i++){
       sb.Append(String.Format("{0}", array[i].ToString());
   }
}

Second:

for(int i=0; i < array.Length; i++){
   if(check){
      sb.Append(String.Format("\"{0}\"", array[i].ToString());
   }
   else{
      sb.Append(String.Format("{0}", array[i].ToString());
   }
}

Upvotes: 3

Views: 295

Answers (4)

Sefe
Sefe

Reputation: 14007

There is no general answer for that, especially on modern CPUs.

In theory

Theoretically, the less branches you have in your code, the better. So since the second statement repeats the branches once per loop iteration, you need more processing time and hence it is less efficient.

In practice

Modern CPUs do what is called branch prediction. That means they try to figure out in advance if a branch is taken. If the prediction is correct, the branch is free (free as in 0 CPU cycles), if it is incorrect, the CPU has to flush its execution queue and the branch is very expensive (as in much more than 1 CPU cycle).

In your specific examples you have two branch types, the ones for the loop and the ones for the if. Since your condition for the if does not change and the loop has a fixed number of executions, both branches are trivial to predict for the branch prediction engine and you can expect both alternatives to perform the same.

In coding practice

Performance considerations rarely have an impact in practice (especially in this case because of branch prediction), so you should choose the better coding style. And I would consider the second alternative to be better in this respect.

Upvotes: 5

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64931

Also, the whole code could be refactored as:

Func<int, string> getText;

if(array.Length > 2) getText = i => $@"A - ""{array[i]}""";
else getText = i => $@"B - ""{array[i]}""";

for(int i = 0; i < array.Length; i++) sb.Append(getText(i));

That is, you define the whole Func<int, string> based on some boolean check, and later you do the whole for loop against the pre-defined Func<int, string> which won't need a check anymore, and also, you don't repeat yourself!

See how I've used interpolated strings, which is a syntactic sugar of regular string concatenation, and I've used verbatim strings to escape quots using double quots.

In summary:

  • You avoid repeating yourself.
  • You avoid many calls to string.Format.
  • You avoid many calls to string.ToString().
  • You reduce code lines.
  • Compiled code is simpler, because delegates end up in a call to a method in a generated internal class, and the rest of operations are just syntactic sugar over regular string concatenation...

I know...

I know that my answer doesn't address the question at all, but I wanted to give the OP some hints on how to optimize the code from a high-level point of view, instead of focusing on low-level details.

Upvotes: 2

Rob Lyndon
Rob Lyndon

Reputation: 12661

Sefe's answer is very interesting, but if you know in advance that the value will not change throughout the loop, then you really shouldn't be checking within the loop.

It is preferable to separate the decision from the loop entirely:

var template = check ? "\"{0}\"" : "{0};
for(int i=0; i < array.Length; i++)
{
    sb.Append(String.Format(check, array[i].ToString());
}

Upvotes: 2

Oleksandr Kobylianskyi
Oleksandr Kobylianskyi

Reputation: 3380

First one is more efficient. But compiler optimizations potentially can fix the latter case during compilation.

Upvotes: -1

Related Questions