Written by

Senior Developer Support Engineer at InterSystems
Article Peter Steiwer · Jan 22, 2020 2m read

Optimizing If-Else Statements for best performance

Do you ever have the desire to optimize your code as much as possible?
Do you have any cases where every nanosecond matters?
Do you use If statements?

This quick tip can help your code run slightly faster with no additional code.

We all know that for each command executed, there is a cost associated with it. Re-ordering your If Statements may lead to small performance gains (size of gains will depend on amount of iterations).

When using If Statements, putting your most likely case in the IF clause will yield the best performance. This is true because for each additional ElseIf clause that is added, all prior clauses must first be evaluated.

Based on my tests, given the following If Statement structure: Clause1...ClauseN-Else. The time to reach Clause1 will be fastest, followed by Clause2, etc... However, this pattern only repeats until ClauseN-1. Else will be slightly faster than ClauseN. It appears that the conditional jump from ClauseN to Else is less expensive than the jump from ClauseN to the end of the If statement, so Else is slightly less expensive than ClauseN. NOTE: See below for the case where N=1.

See the following test case and results:

When N>1:

ClassMethod Run2()
{
    For i=1:1:4 {
        Set time(i,"start")=$zh
        For j=1:1:1000000 {
            If i=1 {
                set a=1
            } ElseIf i=2 {
                set a=1
            } ElseIf i=3 {
                set a=1
            } Else {
                set a=1
            }
        }
        Set time(i,"end")=$zh
    }
    
    W "Time for If: ",time(1,"end")-time(1,"start")," seconds",!
    W "Time for ElseIf #1: ",time(2,"end")-time(2,"start")," seconds",!
    W "Time for ElseIf #2: ",time(3,"end")-time(3,"start")," seconds",!
    W "Time for Else: ",time(4,"end")-time(4,"start")," seconds",!
}

Time for If: .02166 seconds
Time for ElseIf #1: .026443 seconds
Time for ElseIf #2: .035915 seconds
Time for Else: .032695 seconds

When N=1:

ClassMethod Run()
{
    For i=1:1:2 {
        Set time(i,"start")=$zh
        For j=1:1:1000000 {
            If i=1 {
                set a=1
            } Else {
                set a=1
            }
        }
        Set time(i,"end")=$zh
    }
    
    W "Time for If: ",time(1,"end")-time(1,"start")," seconds",!
    W "Time for Else: ",time(2,"end")-time(2,"start")," seconds",!
}

Time for If: .02168 seconds
Time for Else: .015388 seconds

Based on these results, In the case where you have IF-Else, you should put your most common case in the Else Block. In the case where you use If-ElseIf-Else, you should put your most common case in the If Block.

As you can see, these numbers are relatively small compared to the 1 million iterations. However, if you are ever writing code that loops millions of times, reordering your If Statements can save you some time.

Comments

Eduard Lebedyuk · Jan 23, 2020

Interesting article.

Note that comparison with 1 would always be the fastest regardless of where it is:

Here's your code on my PC:

Time for If: .037652 seconds
Time for ElseIf #1: .045029 seconds
Time for ElseIf #2: .057766 seconds
Time for Else: .053267 seconds

And here's a modified code with comparison to 1 third:

ClassMethod Run3()
{
    For i=1:1:4 {
        Set time(i,"start")=$zh
        For j=1:1:1000000 {
            If i=3 {
                set a=1
            } ElseIf i=2 {
                set a=1
            } ElseIf i=1 {
                set a=1
            } Else {
                set a=1
            }
        }
        Set time(i,"end")=$zh
    }
    
    W "Time for If: ",time(1,"end")-time(1,"start")," seconds",!
    W "Time for ElseIf #1: ",time(2,"end")-time(2,"start")," seconds",!
    W "Time for ElseIf #2: ",time(3,"end")-time(3,"start")," seconds",!
    W "Time for Else: ",time(4,"end")-time(4,"start")," seconds",!
}

Running this code yields these results:

Time for If: .109513 seconds
Time for ElseIf #1: .048419 seconds
Time for ElseIf #2: .029746 seconds
Time for Else: .059306 seconds

Regardless of where comparison to 1 happens it would be the fastest one.

0
Vitaliy Serdtsev  Jan 23, 2020 to Eduard Lebedyuk

I have (2019.1.1CE) this is not confirmed:

<FONT COLOR="#0000ff">f </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=1:1:4 </FONT><FONT COLOR="#800080">{
  </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">)=</FONT><FONT COLOR="#0000ff">$zh
  f </FONT><FONT COLOR="#800000">j</FONT><FONT COLOR="#000000">=1:1:1e6 </FONT><FONT COLOR="#800080">{
      </FONT><FONT COLOR="#0000ff">i </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=2 </FONT><FONT COLOR="#800080">{
        </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">a</FONT><FONT COLOR="#000000">=2
      </FONT><FONT COLOR="#800080">} </FONT><FONT COLOR="#0000ff">ElseIf </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=3 </FONT><FONT COLOR="#800080">{
        </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">a</FONT><FONT COLOR="#000000">=3
      </FONT><FONT COLOR="#800080">} </FONT><FONT COLOR="#0000ff">ElseIf </FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">=1 </FONT><FONT COLOR="#800080">{
        </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">a</FONT><FONT COLOR="#000000">=1
      </FONT><FONT COLOR="#800080">} </FONT><FONT COLOR="#0000ff">Else </FONT><FONT COLOR="#800080">{
        </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">a</FONT><FONT COLOR="#000000">=0
      </FONT><FONT COLOR="#800080">}
  }
  </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">i</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)=</FONT><FONT COLOR="#0000ff">$zh
</FONT><FONT COLOR="#800080">}

</FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#008000">"Time for If (i=2): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(1,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(1,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,   </FONT><FONT COLOR="#008000">"Time for ElseIf #1 (i=3): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(2,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(2,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,   </FONT><FONT COLOR="#008000">"Time for ElseIf #2 (i=1): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(3,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(3,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,   </FONT><FONT COLOR="#008000">"Time for Else (i=4): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(4,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(4,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!</FONT>

Time for If (i=2): .109283 seconds Time for ElseIf #1 (i=3): .060785 seconds Time for ElseIf #2 (i=1): .08026 seconds Time for Else (i=4): .109974 seconds

0
Peter Steiwer  Jan 23, 2020 to Vitaliy Serdtsev

Hi @Vitaliy Serdtsev,

Try with larger numbers. With the smaller numbers, there will be slight variations which can flip the order.

With 1e9:

Time for If: 28.111261 seconds
Time for ElseIf #1: 38.782421 seconds
Time for ElseIf #2: 49.21395 seconds
Time for Else: 48.58113 seconds

0
Vitaliy Serdtsev  Jan 23, 2020 to Peter Steiwer

Hi Peter.

Ok.

<FONT COLOR="#0000ff">w </FONT><FONT COLOR="#008000">"Time for If (i=2): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(2,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(2,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,
  </FONT><FONT COLOR="#008000">"Time for ElseIf #1 (i=3): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(3,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(3,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,
  </FONT><FONT COLOR="#008000">"Time for ElseIf #2 (i=1): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(1,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(1,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!,
  </FONT><FONT COLOR="#008000">"Time for Else (i=4): "</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(4,</FONT><FONT COLOR="#008000">"end"</FONT><FONT COLOR="#000000">)-</FONT><FONT COLOR="#800000">time</FONT><FONT COLOR="#000000">(4,</FONT><FONT COLOR="#008000">"start"</FONT><FONT COLOR="#000000">),</FONT><FONT COLOR="#008000">" seconds"</FONT><FONT COLOR="#000000">,!!</FONT>

1e6 Time for If (i=2): .030974 seconds Time for ElseIf #1 (i=3): .045126 seconds Time for ElseIf #2 (i=1): .07144 seconds Time for Else (i=4): .087353 seconds

1e9 Time for If (i=2): 28.59286 seconds Time for ElseIf #1 (i=3): 43.044261 seconds Time for ElseIf #2 (i=1): 82.277535 seconds Time for Else (i=4): 69.212718 seconds

0
Peter Steiwer  Jan 23, 2020 to Vitaliy Serdtsev

Also for your test, the same with my note for Eduard -  the output is hardcoded, so the first output line is for i=1, the second is for i=2, the third for i=3, the last for i=4

0
Peter Steiwer  Jan 23, 2020 to Eduard Lebedyuk

Hi Eduard,

Please note that the output is hardcoded, so your output for "Time for ElseIf #2" is actually for your If statement

0
Vitaliy Serdtsev · Jan 23, 2020
 

And more food for thought:

Class dc.test Abstract ]
{

/// d ##class(dc.test).test()
ClassMethod test(As %Integer 10)
{
  ..Run1(N),..Run2(N),..Run3(N),..Run4(N)
}

ClassMethod Run1(As %Integer)
{
  i=1:1:4 {
    time(i,"start")=$zh
    f j=1:1:{
        i=2 {
          a=20
        ElseIf i=3 {
          a=30
        ElseIf i=1 {
          a=10
        Else {
          a=-4
        }
    }
    time(i,"end")=$zh
  }

  "If i=2: ",?12,time(2,"end")-time(2,"start")," seconds",!,
    "ElseIf i=3: ",?12,time(3,"end")-time(3,"start")," seconds",!,
    "ElseIf i=1: ",?12,time(1,"end")-time(1,"start")," seconds",!,
    "Else: ",?12,time(4,"end")-time(4,"start")," seconds",!!
}

ClassMethod Run2(As %Integer)
{
  i=2,3,1,4 {
    time(i,"start")=$zh

    f j=1:1:a=$case(i,1:10,2:20,3:30,:-4)

    time(i,"end")=$zh
  }

  "i=1: ",time(1,"end")-time(1,"start")," seconds",!,
    "i=2: ",time(2,"end")-time(2,"start")," seconds",!,
    "i=3: ",time(3,"end")-time(3,"start")," seconds",!,
    "i=4: ",time(4,"end")-time(4,"start")," seconds",!!
}

ClassMethod Run3(As %Integer)
{
  i=1,2,3,4 {
    time(i,"start")=$zh

    f j=1:1:a=$case(i,2:20,3:30,1:10,:-4)

    time(i,"end")=$zh
  }

  "i=1: ",time(1,"end")-time(1,"start")," seconds",!,
    "i=2: ",time(2,"end")-time(2,"start")," seconds",!,
    "i=3: ",time(3,"end")-time(3,"start")," seconds",!,
    "i=4: ",time(4,"end")-time(4,"start")," seconds",!!
}

ClassMethod Run4(As %Integer) [ ProcedureBlock = 0 ]
{
  i,time,j,a
  
  i=2,3,1,4 {
    time(i,"start")=$zh

    f j=1:1:d $case(i,1:a1,2:a2,3:a3,:a4)

    time(i,"end")=$zh
  }

  "i=1: ",time(1,"end")-time(1,"start")," seconds",!,
    "i=2: ",time(2,"end")-time(2,"start")," seconds",!,
    "i=3: ",time(3,"end")-time(3,"start")," seconds",!,
    "i=4: ",time(4,"end")-time(4,"start")," seconds",!!
  q
a1 a=10 q
a2 a=20 q
a3 a=30 q
a4 a=-4 q
}

}

USER>##class(dc.test).test(1000000)
If i=2:     .027962 seconds
ElseIf i=3: .043612 seconds
ElseIf i=1: .073138 seconds
Else:       .068023 seconds
 
i=1: .035705 seconds
i=2: .035941 seconds
i=3: .03498 seconds
i=4: .033288 seconds
 
i=1: .078231 seconds
i=2: .052477 seconds
i=3: .066045 seconds
i=4: .07372 seconds
 
i=1: .051371 seconds
i=2: .052017 seconds
i=3: .050972 seconds
i=4: .052397 seconds
 
 
USER>##class(dc.test).test(1e6)
If i=2:     .060933 seconds
ElseIf i=3: .071999 seconds
ElseIf i=1: .094509 seconds
Else:       .096684 seconds
 
i=1: .058554 seconds
i=2: .058182 seconds
i=3: .059299 seconds
i=4: .054863 seconds
 
i=1: .09973 seconds
i=2: .074734 seconds
i=3: .087673 seconds
i=4: .097123 seconds
 
i=1: .082372 seconds
i=2: .084538 seconds
i=3: .081647 seconds
i=4: .079353 seconds
0