If() and if..then speed differences

Mine was just like this so only worked on string:

Public Function MyIf(check as Boolean, a as String, b as String) As String
  #Pragma DisableBackgroundTasks
  #Pragma DisableBoundsChecking
  
  if check then
    return a
  end if
  
  return b
  
End Function

1 Like

Surprising findings. I (think I) remember when the ternary If was introduced I did some benchmarks and ternary was notably faster.

1 Like

i think the “bottle-neck” is this = and local variables.

somehow in mind

t(1)="11111111111111111111111111111"
t(2)="2222222222222222222222222"
use = if(<expression>, 1,2) '<- a enum would be good
if <expression> then use = 1 else use = 2
t(use)

Seems non-sense to me. Can you prove what you tried to say with numbers? By numbers I mean measuring the times elapsed and comparing.

if you define this array once (outside of method scope) you can access it by index so there is no string copy.
if your ifthen or iif is in a method the access to the string is faster in both cases.

its not t = “abc” again and again
just use t(1) with the declare once t(1)=“abc”

Still non-sense to me. I bet that if you measure what you think that can be faster, will be really slower.

Remember, we are talking about speed of this:

var t as string
t = if(<expression>, "1","2")

Versus

var t as string
if <expression> then
t = "1"
else
t = "2"
end

And now versus:

What Markus thinks that can be faster and I didn't get

With this code

#Pragma Unused args
#Pragma BackgroundTasks Off
#Pragma BoundsChecking Off

Var Startms As Integer
Var Endms As Integer
Var result As Boolean

Startms = System.Microseconds
For i As Integer = 0 To 999999
  result = If(i mod 2 = 0, True, False)
Next i
Endms = System.Microseconds

Var inLine As Integer = Endms - Startms

Startms = System.Microseconds
For i As Integer = 0 To 999999
  If i mod 2 = 0 Then
    result = True
  Else
    result = False
  End If
Next i
Endms = System.Microseconds

Var ms As Integer = Endms - Startms

Break

Startms = System.Microseconds
For i As Integer = 0 To 999999
  If i mod 2 = 0 Then
    result = True
  Else
    result = False
  End If
Next i
Endms = System.Microseconds

ms = Endms - Startms

Startms = System.Microseconds
For i As Integer = 0 To 999999
  result = If(i mod 2 = 0, True, False)
Next i
Endms = System.Microseconds

inLine = Endms - Startms

Break

I get 145999 for inline and 143349 for ms at the first break and 103317 for inline and 189816 for ms at the second break. Not sure why there’s difference in the order of the process. I do get similar results on subsequent runs though.

This is running on a Mac M1 and is a console app.

Put prints on the times, build and run. Let’s remove the debugger interference.

Basically it confirms if() is slower which shouldn’t be the case.

Maybe someone of Xojo Inc could clarify this?

3 Likes

i made a test for my idea and it looks equivalent so it is not worth that change.

option 1

Var ms As Double = System.Microseconds
Var t As String
Var b As Boolean
Var a As Int64
Var l As Integer
Var toggle As Boolean = False
For a = 0 To 1000000
  toggle = Not toggle
  t = If(toggle , "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB")
  l=l+t.Length
Next a
MessageBox "If() Microseconds=" + Str( System.Microseconds - ms)

option 2

Var ms As Double = System.Microseconds
Var t As String
Var b As Boolean
Var a As Int64
Var l As Integer
Var toggle As Boolean = False
For a = 0 To 1000000
  toggle = Not toggle
  If toggle = True Then
    t="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  Else
    t="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
  End
  l=l+t.Length
Next a
MessageBox "if then Microseconds=" + Str( System.Microseconds - ms)

option 3

'(Outside of Method Scope)
Var t(2) As String
t(1)="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
t(2)="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"

Var ms As Double = System.Microseconds
Var b As Boolean
Var a As Int64
Var l As Integer
Var use As Int8
Var toggle As Boolean = False
For a = 0 To 1000000
  toggle = Not toggle
  If toggle Then
    use=1
  Else
    use=2
  End
  l=l+t(use).Length
Next a
MessageBox "by index Microseconds=" + Str( System.Microseconds - ms)

For me, the Trinary/Inline version is faster than “normal” if/then when assigning an integer vs. a string.

in other words:

someInteger = if(1 = 1, 1, 2)

is much faster than

someString = if(1 = 1, "a", "b")

with all other things being equal.

In fact the single line/trinary form:

someInteger = if(1 = 1, 1, 2)

is faster than the traditional if/then, even if it’s also setting an integer variable.

sample project here: Dropbox - sampleProject.xojo_binary_project.zip - Simplify your life

Ok, I’ll take that as a “it failed”.

you can test my example above.
i agree i had more speed hoped-for.

No need, I believe in you.

Its quite normal that integer assignment is faster than string. String is internally a object that carries data, while integer is basically primitive.

1 Like

Sure. But the trinary/inline version is faster than the traditional/multi-line version when assigning an integer; this is what I found interesting.

2 Likes

I get 1416 vs 2122 so yes I can reproduce that indeed.

So for peoples knowledge chest then so far as it stands then in place if (operator if) is faster for int, but slower for string, than multiline if’s.

1 Like

Interesting conclusion. Now t find out why the string if() is slower than the normal string if end if.

Whatever is done, the in-register optimization seems able to do good reuse of a register value but not a referenced value (pointer).

1 Like

As I always try to squeeze ever speed out of data processing I found another odd problem. But this is more related to the new API2.

Just do a test with the ‘old’ Instr() and the new IndexOf()

One of my apps uses INSTR a lot and the process takes a typical 32 seconds to do.
But when I change it to INDEXOF (which is the new API2) it takes a whopping 4min9secs.That almost 8 times slower.
When I use ComparisonOptions.CaseSensitive , it takes even longer: 5min42secs.

Now that’s bad and really needs optimisation.

So PLEASE do not remove INSTR (which is deprecated) until IndexOf is equally as fast (or faster).

1 Like