If() and if..then speed differences

There’s a dropbox link above for the sample project I put together if anyone feels like running it on Windows. (or Linux!)

The project is 2021 r2.1 project, fyi.

I ran this project on macOS as a build, and here as Christian predicted the explicit If version is always leading or on par with inline. Inline is only faster in a debug build.
String and Variant(String) times differ enormously with explicit leading in every case.

In a Windows 10 build results are quite similar to macOS (even sometimes twice as fast in Parallels as on the host Mac system), with the exception of inline variant being a bit faster, but double and integer inline will not finish?!?!

EDIT: The latter stops when the loop counter is increased > 10 Mill. – ternary tests do exit correctly.

EDIT II: Posted some thread findings I did not expect here.

A little additional information. OS version and processor (at least on Mac) also seem to affect performance.

On a M1 mini on Big Sur, inline was generally faster (with the exception of working with strings) at lower counts. (e.g. on the M1 mini, 10M loops when setting an Integer was faster than explicit)

This advantage decreased as you upped the number of loops, but…

I’d say in general, the performance difference between inline and explicit is immaterial for typical uses, *except when you’re working with the String type.

Working with Strings shows materially worse performance when using the inline/trinary version of “If”.

If you are doing a large amount of conditional logic operations which are setting String variables, the inline version of If() should (in my opinion) be avoided until its performance is brought inline with the explicit, If…Then, version of “If”.

(p.s. this seems to be true regardless of optimization level set when compiling the testing application)

Cause internally they seem to use Text which has always been slower. CPU diffrences will always be there, maybe xojo could ditch the Text type alltogether in the in-line if we should see some improvements there.

Wasn’t Text deprecated?

Yes it is but xojo still uses it aparently, which is kinda… you know … slow (especially on windows).
see here: MBS Blog - If vs If in Xojo

Assuming nothing has changed in this area of the compiler…

The If() expression is an operator and has to be to avoid evaluating the not-chosen expression. The overhead with strings only occurs if both value expressions are quoted literals.

The short version of “why” is that the compiler has to choose a type for quoted literals (String vs Text). In most cases this is obvious from the context that the literal is used in, but the compiler doesn’t know when compiling the If operator what the result should be and just defaults to Text. Then when it gets used as a String it has to do a conversion.

Ideally the compiler wouldn’t have the complexity of deciding the type of quoted literals, but that ship has sailed. One option would be to change If to prefer the result type to be String for quoted literals but changing the semantics could break things in subtle ways – perhaps ways that nobody cares about at this point. Another option would be to have an optimization pass that cleans up the generated LLVM IR by finding calls to RuntimeStringFromText that take a Text literal and replacing it with an equivalent String literal.

20 Likes

Good to hear from you Joe.

6 Likes

So I basically understand it is hard to fix this for Xojo. Hmmm… not good.

And good to hear from you!

Sounds like with deprecation of text, the compiler should prefer the use of string over text in such cases.
Maybe worth a feature request?

3 Likes

Please don’t further relegate Text to the dustbin. At least not until String handles Unicode properly: Feedback 65401

2 Likes

Text is so slow on average it hogs the whole language if not handled properly. I’d rather have it gone (at least by default), keeping it deprecated is fine but using it as a default on the if() etc… seems pretty bad.

4 Likes

Welcome back my old friend, and educating us all again :slight_smile:

1 Like

Would doing soemthing like this help?


Var  resStr, forceStr as String = ""

resStr = if  (i=27, "first string" + forceStr, "second string" + forceStr)

4 Likes

With ctype it’s definately faster so…

Result is a String
result = If(true, CType("true", String), CType("false", String))

In order of speed:
1 - Variables As String took: 0.0376 Seconds, iterations: 100000
2 - Constants As String took: 0.0415 Seconds, iterations: 100000
3 - Literal String CType took: 0.0440 Seconds, iterations: 100000
4 - Literal String took: 0.0678 Seconds, iterations: 100000
5 - Variables As Text took: 0.0692 Seconds, iterations: 100000
6 - Constants As Text took: 0.0702 Seconds, iterations: 100000

edit: added constants (from post below @Kem_Tekinay)

This should be the same:

const kTrue as string = "true"
const kFalse as string = "false"

result = if(true, kTrue, kFalse)
2 Likes

Seems to be a little faster

Then why don’t you or Rick explain why instead of taking cheap shots with memes and stackoverflow-esque comments?

1 Like