Cooperative threads: 2023R4 faster than 2024R3

As reported in other threads, I have been timing cooperative and preemptive threads using 2024R3. For the same Xojo code (except for thread.type statements), dedicated hardware and dataset, here are the timings for cooperative threads using 2024R4 and 2023R4:
2024R4: 4 hours 7 minutes 8 seconds (± a few minutes in later runs)
2023R4: 3 hours 39 minutes 21 seconds (± a few minutes in later runs)

This is almost 30 minutes difference! Have you noticed anything like this?

Yes, but I’m seeing the difference in speed between versions 2024r2 and 2024r3. Performance is r3 is about 25% slower than r2.

I’ve been trying to pin down the cause of this, to no avail. All I know so far is:

  • the same code in a cooperative thread runs about 20% faster than when it is set to preemptive
  • 2024r3 introduces about 25% slower performance

The fastest version I have running is 2024r2.

I don’t know, but I wonder if string processing got even slower in r3? Our thread is converting a lot of arrays and memoryblocks to strings and storing them in a database (potentially millions of records).

The reports I’ve read are like: Debugging code it feels like a rock, but the built app is a rocket.

Not here. My report above is for the built app.

If you are on macOS you could use XCode Instruments to profile the code built with both versions of Xojo.

Running the Instruments Timing tool, something appears in the r3 trace that doesn’t in r2, which appears to be slowing things down:

RuntimeGetCurrentException XojoFramework
tlv_get_addr libdyld.dylib

(I have no experience reading these reports.)

tlv_get_addr is related to thread local variables so this might be something William had to change to get preemptive threads to co-exist with cooperative threads.

I suggest you log a bug with the Instruments reports from both versions and if possible, a sample project.

I’m seeing stack checking in r3 that doesn’t appear in r2. I have that disabled in the thread, which does call methods outside itself. As I understand the way it was working previously, as long as the #pragma was set at the top of the thread, that was inherited by any outside methods called by the thread. Could it be that #pragmas are handled differently in r3? Or am I wrong in the first place about previous versions?

My understanding was that #pragma only affected the method it was in and no other method.

Maybe there were special rules for threads but I cannot remember ever reading about them.

Maybe #pragma wasn’t working correctly previously and got fixed during the changes?

I would query this with Xojo.

Unfortunately, that is not true for BreakOnExceptions. BreakOnExceptions applies to the stack (including methods you call) until it would “go out of scope”.

I have an example project link handy from the last time this came up: https://tim.gd/VZzIP

Maybe all #pragma functions work like that. The documentation could really do with a bit more detail.

1 Like

Serious bugs in 2024R3 with threads, for example sleeping the main thread is broken, see Thread.SleepCurrent() broken in 2024R3

I’ve filed a confidential report with the Instruments traces.

1 Like

Just out of curiosity, how many threads are you testing with?