Page 1 of 1

IF vs SELECT speed test

Posted: Sat Feb 08, 2025 7:45 pm
by minimy
Was looking to improve speed in an old basic Atom cpu laptop and did this program to test speed IF vs SELECT.
I put it as an anecdote, I found it interesting

RESULT WAS:
SELECT: 470ms
IF: 434ms

And the winner is IF

In the I7 i cant see :lol:

Code: Select all

DisableDebugger

t= ElapsedMilliseconds()
For p= 1 To 10000000
  a= Random(10,1)
  Select a
    Case 1
      b=a
    Case 2
      b=a
    Case 3
      b=a
    Case 4
      b=a
    Case 5
      b=a
    Case 6
      b=a
    Case 7
      b=a
    Case 8
      b=a
    Case 9
      b=a
    Case 10
      b=a
  EndSelect
Next p
t1= ElapsedMilliseconds()-t

t= ElapsedMilliseconds()
For p= 1 To 10000000
  a= Random(10,1)
  If a=1
    b=a
  ElseIf a=2
    b=a
  ElseIf a=3
    b=a
  ElseIf a=4
    b=a
  ElseIf a=5
    b=a
  ElseIf a=6
    b=a
  ElseIf a=7
    b=a
  ElseIf a=8
    b=a
  ElseIf a=9
    b=a
  ElseIf a=10
    b=a
  EndIf
Next p
t2= ElapsedMilliseconds()-t

MessageRequester("TEST","IF vs SELECT"+#CR$+"SELECT: "+Str(t1)+#CR$+"IF: "+Str(t2))


Re: IF vs SELECT speed test

Posted: Sat Feb 08, 2025 10:26 pm
by mk-soft
Another one compare these unnecessary.
The compiler makes the best of it anyway (optimisation)

If and Select 40 ms equal

I find Select clearer than several If and Elseif

Re: IF vs SELECT speed test

Posted: Sat Feb 08, 2025 11:31 pm
by idle
you won't see much difference as the generated code is much the same.

Re: IF vs SELECT speed test

Posted: Sun Feb 09, 2025 2:27 am
by STARGĂ…TE
Keep also in mind that the CPU is "waked up" after the first loop und runs at higher frequencies in the second loop.
If you first measure the IF and then the SELECT part, SELECT is the winner ;-)
In any case, both constructs are equal fast.

Your code:
---------------------------
TEST
---------------------------
IF vs SELECT
SELECT: 134
IF: 131
---------------------------
OK
---------------------------
Swap both loops:
---------------------------
TEST
---------------------------
IF vs SELECT
SELECT: 132
IF: 135
---------------------------
OK
---------------------------

Re: IF vs SELECT speed test

Posted: Sun Feb 09, 2025 3:18 am
by AZJIO
The Random() function is not a good solution for checking the exact speed. RandomSeed() is required.

Re: IF vs SELECT speed test

Posted: Sun Feb 09, 2025 11:24 am
by SMaag
The difference between If ans Select in the Assembley

Code: Select all

; If a=1
  MOV    r15,qword [v_a]
  CMP    r15,1
  JNE   _EndIf4
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; ElseIf a=2
  JMP   _EndIf3
_EndIf4:
  MOV    r15,qword [v_a]
  CMP    r15,2
  JNE   _EndIf5
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; ElseIf a=3
  JMP   _EndIf3
_EndIf5:
  MOV    r15,qword [v_a]
  CMP    r15,3
  JNE   _EndIf6
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; ElseIf a=4


; Select a
  PUSH   qword [v_a]
; Case 1
  MOV    r15,1
  CMP    r15,[rsp]
  JNE   _Case1
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; Case 2
  JMP   _EndSelect1
_Case1:
  MOV    r15,2
  CMP    r15,[rsp]
  JNE   _Case2
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; Case 3
  JMP   _EndSelect1
_Case2:
  MOV    r15,3
  CMP    r15,[rsp]
  JNE   _Case3
; b=a
  PUSH   qword [v_a]
  POP    qword [v_b]
; Case 4
  JMP   _EndSelect1
With changing the Loop Constructions For, Repeat While, or If, Select you can't change the speed!

removing jumps or Procedurecalls is much more effective. Unrolling Loops is a way to speed up.

If you show more of the code, we can analyse it and maybe find some bottleneck!

Re: IF vs SELECT speed test

Posted: Sun Feb 09, 2025 10:49 pm
by idle
timing If's and Selects isn't really that useful outside of the context of a more complex program.

When the CPU encounters an IF it will generally assume that the 1st clause is the desired outcome but after a few loops it will also have tried to guess which branch is the preferred outcome it's self but setting the 1st clause as being the desired one is the better option for cache coherency and will lead to less cache hits. Also if you have independent code in the branches, you will also get the benefit of out of order executions and essentially you can get your else for free as the cpu will process the branches in parallel and then give you the result, though it's often hard to make the code independent.

Fortunately you don't really need to be so concerned about the code layout now as the c optimizer will try to eliminate branches, swap them around, unroll loops and inline procedures and the more native code you write, the more chance it will have at optimizing it. Then there's also LTO (link time optimizer) where the linker can rearrange lib functions to reduce cache hits again.

Re: IF vs SELECT speed test

Posted: Mon Feb 10, 2025 4:49 am
by AZJIO
SMaag wrote: Sun Feb 09, 2025 11:24 am removing jumps or Procedurecalls is much more effective.
I do not agree. Eliminating the calls of functions makes the code unreadable, and all this for the sake of one nanosecond, it is inappropriate.

Code: Select all

DisableDebugger
EnableExplicit

Procedure Test()
	Protected x = 1
EndProcedure

Define StartTime, i
StartTime = ElapsedMilliseconds()
For i = 0 To 10000000
	Test()
Next
StartTime = ElapsedMilliseconds() - StartTime
EnableDebugger

Debug StartTime

Re: IF vs SELECT speed test

Posted: Mon Feb 10, 2025 12:39 pm
by SMaag
I do not agree. Eliminating the calls of functions makes the code unreadable, and all this for the sake of one nanosecond, it is inappropriate.
yes absolutley right!

But inlining short functions or use Macros instead seeds up! I agree, it only makes sense if you have regulary millions of calls. Like in Pixel operations or data sience ...

Think about such things only if you see your program is to slow. Under a execution time of a second, the user won't feel it.

Code: Select all

DisableDebugger
EnableExplicit

Procedure Add(x, n)
	ProcedureReturn x + n
EndProcedure

#Mio = 1000000
#Loops = #Mio * 10

Define t1, t2, i, sum

; first a loop to startup CPU! eliminates first test is solower
For I = 1 To 10000
  sum+I
Next

I = 0

t1 = ElapsedMilliseconds()
For i = 0 To #Loops
	Add(sum,I)
Next
t1 = ElapsedMilliseconds() - t1

sum = 0

t2 = ElapsedMilliseconds()
For i = 0 To #Loops
	sum + i
Next
t2 = ElapsedMilliseconds() - t2


EnableDebugger

OpenConsole()
PrintN("With Proc = " + Str(t1))
PrintN("Inline = " + Str(t2))
Print("Press a key to exit")
Input()