Best practice for creating if

Asked

Viewed 2,644 times

5

Which of the two code options has better performance?

I’m going to show you a very simple example, usually there’s more code inside the if.

To)

string mensagem = "OI";
if(exibirAdeus)
   mensagem = "Adeus";

B)

string mensagem = "";
if(exibirAdeus)
  mensagem = "Adeus";
else 
  mensagem = "OI";

9 answers

7

I do not know if it is worth thinking about performance of such a short fragment and execution so fast. However we can make the following analysis:

Under A) you initialize the variable and it will only be updated if the expression exibirAdeus be true. In B) you initialize the variable with a value that will never be used, this way you will have the cost of updating the variable independent of the value of exibirAdeus.

This way I tell you that A) has better performance than B). But not because it is C#, but because of the algorithm used.

  • A) does not necessarily perform better than B). The correct performance would be equal or better.

  • I was curious to know why there was a negative vote here. I wanted to learn where the problem of the answer is.

6


The question is pertinent yes if the code block in if contains high computational complexity, written in the database or in files, etc..

The ideal between the two would be the (A).

Why Performance(A) >= Performance(B)

Case 1: the implementation of the programme has always exibirAdeus = true, Performance(A) = Performance(B). Both (A) and (B) will end up having the same flow:

Algorithm (A), Algorithm (B):

1. Atribui "" ou "Oi" para `message`
2. Verifica `exibirAdeus == true`
3. Atribui "Adeus" para `message`

Case 2: the implementation of the programme has 1 or more exibirAdeus = false, Performance(A) > Performance(B). Because for such cases (B) will be more costly:

Algorithm (A):

1. Atribui "Oi" para `message`
2. Verifica `exibirAdeus == true`: falso, não faz nada (message já é "Oi"). continua adiante.

Algorithm (B):

1. Atribui "" para `message`
2. Verifica `exibirAdeus == true`: falso, precisa atribuir "Oi".
3. Atribui "Oi" para `message`

Real World

However, if this block is small and of low complexity, it becomes extremely unnecessary.

The path you would follow is: How readable and easy to maintain this code (readability & maintainability). I say this because there is a consensus* that in this case presented, you should be more concerned with placing the keys ({}) to demarcate the blocks of the if-Else.

string mensagem = "OI";     // padrão: caso mais provável...
if (exibirAdeus) {
   mensagem = "Adeus";
}

or, if the code starts to become more complicated as remembered by C. E. Gesser:

private bool Teste(){
    [..]
    string mensagem = initMensagem(condicao);
    [..]
}

private string initMensagem(bool condicao){
    if (condicao) {
      return "Adeus";
    }
    return "OI";
}

Another common case

string message = "";
if (condicao == 1){
   message = "blablbla";
}
else if (condicao == 2){
   message = "Lorem";
}
else if (condicao == 3){
   message = "Ipsum";
}
[..]
else {
   message = "Dolor";
}

This would be better written** for performance, readability and maintainability:

string message = "";
switch (condicao) {
    case 1: 
       message = "blablbla";
       break;
    case 2: 
       message = "Lorem";
       break;
    case 3: 
       message = "Ipsum";
       break;
    [..]
    default: 
       message = "Dolor";
}

*
https://softwareengineering.stackexchange.com/questions/16528
https://softwareengineering.stackexchange.com/questions/2715
https://stackoverflow.com/questions/15786949

**
https://stackoverflow.com/questions/445067
https://stackoverflow.com/questions/767821
https://stackoverflow.com/questions/395618

  • 1

    For more complicated cases, code organization is better by refactoring startup logic to another function: string message = initMessage(condicao);

  • Agree! Better yet!

  • @Andréfigueiredo porque e' que Porque Performance(A) >= Performance(B)?

  • "=" because case exibirAdeus==true in all cases during execution, Else will never be executed; the flow will always be the same for both cases: always be created the variable, initialized, checked exibirAdeus==true, and the variable updated to "Goodbye". ">" for other cases where there will be some exibirAdeus==false , where (B) will denigrate performance at the cost of updating the variable - as more exibirAdeus==false, (A) will not update.

  • The flow has no cost. What it costs is the creation of objects. And in case A, if exibirAdeus==false, 2 objects are created: "HI" and "Goodbye" - and the object "OI" was unnecessarily created. The ideal case would be case C, as demonstrated in my reply.

  • Be curious about why to use case is less costly than various ties if\else.

  • 2

    @Felipe. switch and' more efficient than if/else if there are 5 or more cases. If there are >=5 cases, the switch and' implemented using a hash table/lookup table - and all cases will have constant access O(1). In the case demonstrated by @Andréfigueiredo, if/Else would have better performance.

  • 1

    @Felipe.Watch, this is basically what @dcastro said. The detailed explanation is in the links** in the English OS. So to identify which blocks if/else and switch are wide, I put a [..].

  • @dcastro updated the answer with why I believe Performance(A) >= Performance(B)

  • In fact, the step 1. Creates string message does not occur at runtime.

  • Well remembered @Paulomorgado, I updated the answer correctly

Show 6 more comments

4

It is worth mentioning one more option that escaped in the examples presented. Here using the ternary operator.

string mensagem = exibirAdeus ? "Adeus" : "OI";

3

The best case isn’t A nor B. IS C:

string mensagem;
if(exibirAdeus)
  mensagem = "Adeus";
else 
  mensagem = "OI";

In A:

  • if displayAgod == true, 2 objects are created ("HI" and "Goodbye")
  • if displayAgod == false, 1 object was created ("Hi")

In B:

  • if displayAgod == true, 2 objects are created ("" and "Goodbye")
  • if displayAdeus == false, 2 objects are created ("" and "Hi")

In C:

  • if displayAgod == true, 1 object was created ("Goodbye")
  • if displayAgod == false, 1 object was created ("Hi")

2

Taking into account its algorithm, for the processor the difference is almost insignificant (as almost everyone said) however it is obvious that if that if is within a loop for billions this tiny difference becomes more sensitive. I think it is worth thinking about the semantics of what you are writing and see if it makes more sense the first or the second, thus improving readability and understanding.

2

As @Lizard correctly mentioned, performance depends on the probability of the condition and also on the optimization that the processor is able to do. However, I would add here the frequency of use of this routine.

Behold this very interesting question about C processing speed. Modern processors are able to process multiple instructions per cycle, so if the result of the boolean expression is almost always the same, the processor has the ability to "predict" the result and optimize the processing as if the if did not exist.

I don’t know how advanced the C#compiler is, but if even in a high-level language like Ruby there was performance gain by processor-dependent optimizations, then C# would not be an exception.

Also, if a routine like this is used frequently, the initial string is already loaded in cache and the cost of pointing a variable at it will be very small. In the second example, you are pointing to an empty String, which already requires variable assignment processing.

Finally, comparing with the common bottlenecks of performance, the difference of these stretches is practically zero. And this can be applied to most languages.

On the other hand, it is important to emphasize that if, in addition to attribution, there is any kind of processing on the object the scenario can change drastically. After so many statements that "it makes no difference," one could opt for the A alternative and add a conversion to upper case, for example.

2

Among To and B, the most efficient would be To. But the best would be a third, a C:

string mensagem;
if(condicao)
  mensagem = "Adeus";
else
  mensagem = "OI";

But the efficiency of the algorithm revolves around the condition it is used, probability, so we consider the worst case. In To would have to change "OI" for "Adeus" after checking the condition, and in B would change the "" for "OI" or "Adeus" after checking the condition, whatever. Now the question must come, why C if she looks so much like B, which is worse than To? Because the assignment in B string mensagem = "" generates an assignment more independent of the case. In To the chance of a change in the value is 50%, and in C the chance of there being a change does not exist, there will always be an assignment only.

In fact the algorithm is very simple to consider its efficiency, but within a looping, or two, being executed thousands of times, with several possibilities, the relevance of something simple becomes important, making the running time greater.

Consideration: The compiler will always check for a else, is not a further process, it is something inherent to the conditional if.

1

The alternative "A", is very worthwhile if there is a greater chance of the message being "HI". For example, it is known that there are more men than women in a given state.

When making the registration, worth doing:

char sexo = 'M';
if (mulher)
    sexo = 'F';

However, don’t worry about this kind of thing. The processor has a very large capacity and the difference in runtime is one thousandth. For example, one of my teachers said that:

int A = 10;

is 0.000014 faster than

int A = 2 * 5;

But tell me, will 0.000014 make a difference in its application? Of course not, but if you’re curious about the time difference, do the following. Declare a Stopwatch, run method A, and then stop and display the elapsed time. Then declare another Stopwatch, run method B, and then display the time and still see the difference between the two. Stopwatch marks the time past your stop (like a stopwatch). You can test (:

EDIT

EXAMPLE OF USE:

Stopwatch sw = new Stopwatch();
sw.Start();
//seu código aqui
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds.ToString());
  • 2

    In fact most compilers will solve 2 * 5 at build time and only store 10 at run time.

  • 1

    I may have been mistaken then. My teacher taught me so.

  • 5

    May my teachers forgive me but Stack Overflow is the best programming teacher I’ve ever had in my life!

  • Who knows English should read the series of posts on benchmark that the Eric Lippert wrote on http://tech.pro/blog/1293/c-performance-benchmark-mistakes-part-one

0

This will depend on case by case. If exibirAdeus for false in most cases, alternative A is more efficient, especially if the initialization of the variable is costly. Otherwise, it will make very little difference, it is more a matter of style same.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.