The potential impact of an if statement inside a loop

Assuming we have Boolean check = false , and the value for this variable is always either true or false, which means that it never changes through the loop, will it be more efficient to calculate the efficiency than the last?

Firstly:

 // 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()); } } 

The 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()); } } 
+5
source share
4 answers

There is no general answer for this, especially on modern processors.

In theory

Theoretically, the less branches you have in your code, the better. Since the second statement repeats branches once per iteration of the loop, you need more processing time and therefore less efficient.

Almost

Modern processors perform the so-called branch prediction. This means that they are trying to figure out in advance if the branch is taken. If the prediction is correct, the branch is free (free, as in 0 CPU cycles), if it is incorrect, the CPU must reset its execution queue, and the branch is very expensive (as in more than 1 CPU cycle).

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

In coding practice

Performance indicators rarely have an impact in practice (especially in this case due to branch prediction), so you should choose the best coding style. And I would consider a second alternative to be better in that regard.

+5
source

In addition, all code can be reorganized 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 logical check, and then you run the entire for loop against the predefined Func<int, string> , which is no longer needed for verification, and you don’t repeat!

See how I used interpolated strings, which are the syntactic sugar of regular string concatenation, and I used shorthand strings to avoid double quotas.

In short:

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

I know...

I know that my answer does not address the question at all, but I wanted to give the OP some tips on how to optimize the code from a high-level point of view, rather than focusing on low-level details.

+3
source

The answer to Sefe is very interesting, but if you know in advance that the value will not change throughout the cycle, you really should not check in the cycle.

It is advisable to completely separate the solution from the cycle:

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

The first one is more effective. But optimizing the compiler could potentially fix the last case at compile time.

-1
source

Source: https://habr.com/ru/post/1261870/


All Articles