Optimizing speed with crazy code

Xojo needs for 10^6 function calls 80ms, to avoid function calls, you can use GoTo :face_vomiting: .
But the GoTo implementation is 20 times faster.

Xojo 2020R1 on iMac19,1 macOS 10.15.6
Compiler Opt-Level: aggressive

#Pragma BackgroundTasks       False
#Pragma BoundsChecking        False
#Pragma BreakOnExceptions     False
#Pragma NilObjectChecking     False
#Pragma StackOverflowChecking False

Var m As Double = System.Microseconds

Var Me_blockSize As Integer
Var Me_idx As Integer
Var CallFunctionID As Integer
Var ReturnID As Integer
Var i As Integer

Me_idx = 0
Me_BlockSize = 10^6

While Me_idx < Me_BlockSize
  
  CallFunctionID = 1
  ReturnID = 1
  GoTo FunctionList
  ReturnID_1:
  
  CallFunctionID = 2
  ReturnID = 2
  GoTo FunctionList
  ReturnID_2:
  
  CallFunctionID = 2
  ReturnID = 3
  GoTo FunctionList
  ReturnID_3:
  
Wend

m = (System.Microseconds - m) / 1000
MessageBox "Duration: " + m.ToString + " ms"
Return

FunctionList:
Select Case CallFunctionID
Case 1
  Me_idx = Me_idx + 1
Case 2
  i = i + 1
Case 3
  ' unused
End Select

Select Case ReturnID
Case 1
  GoTo ReturnID_1
Case 2
  GoTo ReturnID_2
Case 3
  GoTo ReturnID_3
End Select

Sounds as assembler coding to me. Function calls are “slow”. Xojo is not the answer to all problems

1 Like

Using Goto in a loop is a known cause of memory leaks. DON’T USE GOTO.

3 Likes

Sure, spaghetti code is faster, but it becomes progressively much more difficult to maintain. You have to ask yourself, is it really worth it to gain milliseconds in speed?

memory leak? memory is cheap :wink:

I have to parse a 75GB XML-File and my monolitic code slows down as i add a function in my MainLoop. I have duplicated (copy&paste) the funktion 3 times, speed now OK.

If readability is secondary to speed (and I mean, really secondary), do whatever works to achieve gains. But at the very least, comment the heck out of it.

Yes. 75*10^9 loops and the time differs approx. 5 hours vs. 20 min.

Pass the spaghetti. :grinning:

1 Like

Thanks to the LLVM compiler, we’re getting a lot closer to assembler speed.

I bet I can write something even faster than whatever the final intended code will be full of gotos, but… without gotos, and without leaks. The price to pay usually is having large blocks of redundant code.

2 Likes

Memory leaking is not the same as memory intensive use, memory leaks crashes systems at some point.

4 Likes

Have you tried using the aggressive setting for the compiler? AFAIK, that opens up a few more optimisations to the underlying LLVM compiler (computed gotos, loop unrolling, tail call optimisations, etc).

Yes, Compiler Opt-Level = aggressive. Every function in a Loop takes 80ms per 10^6 calls.
In my project i simply duplicate the code (copy&paste). The GoTo code was only for testing.

Btw. Me.Propertys in Classes are slower then Vars (Dims) and function calls in XoJoScript much faster.

That shouldn’t come as a surprise. OOP comes with a price. For every instance variable or method, the handle of the instance will always be added as input parameter, and of course that takes time. And may explain at least partially why the “bad” Gotos being basically translated to jumps in execution code table are faster than method calls which contain a lot more internal handling.

In own performance tests I have found property getters to add a considerable amount of processing time, so an easy method to avoid their overhead is to address their underlying private property whenever possible (or caching it), as an own example.

But depending on your code and desired target platform, you may often find the best solution can include both – textbook like OOP code and performance. Sadly that might only work through plugins or declares, like Accelerate framework on macOS/iOS which can give you enormous parallel bulk processing performance on Xojo MemoryBlocks.