Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The potential impact of an if statement inside a loop

Tags:

c#

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());
   }
}
like image 996
Arnold Zahrneinder Avatar asked Jan 04 '23 20:01

Arnold Zahrneinder


2 Answers

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.

like image 173
Sefe Avatar answered Jan 13 '23 07:01

Sefe


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.

like image 44
Matías Fidemraizer Avatar answered Jan 13 '23 07:01

Matías Fidemraizer