Do you have Intel builds from both compilers + some test data available and I will see if I can find anything using XCode Instruments.
Actually, I’ve figured it out. Something has changed about thread scheduling. Maybe intentionally, maybe not, but it’s definitely different.
I set my background threads to the lowest priority constant since they aren’t user-facing. In 2025r2.1, setting those threads to normal priority helps. The read-intensive operation returns to within margin-of-error of 2023r4, but my write-intensive operation is still slower at 12 minutes 34 seconds. It’s sure an improvement over 21 minutes, but a far cry from 53 seconds. My guess is high priority will get the rest of the performance back, but I haven’t tested that yet. It’s clear the thread priority plays a major factor here.
So now the question is what changed? Going to comb through release notes again. Now that I know it’s thread-related and not database-related, I might find something relevant.
They added support for preemptive threads in 2024r3, many changes internally from what I understand.
Sure. And I use them in new projects. But I can’t find anything definitive that says I should expect an outcome like this. I’m hesitant to set my background threads to high priority, especially since there’s no documentation about what to expect.
I remember some reports that cooperative threads are slower after that change, maybe needed as they have to coordinate the new threads. I’m sure others with more knowledge can give you better information.
I hope you get your speed back.
I think this was due to the overhead added to the framework to implement thread-safe access to data and code. It was a small hit across the entire framework but the gains in performance with preemptive threads made it worthwhile.
Glad you’ve gotten a foothold on the problem. It would be tedious, but have you considered incrementally stepping backwards in Xojo versions until the problem disappears? That might narrow down the change that could be causing this.
Yeah, I have considered it. I’m kind of avoiding that since I don’t even have the other versions installed, so I’d have to get them setup with their plugins and all that. And since this is most evident on Windows, that’s where I’ve been doing all this testing, which means I have to go through the installers, UAC prompts to install plugins, uninstallers to remove them when done… None of it is hard, just kind of annoying for information that isn’t critical.
maybe your cooperative threads running so fast or long that the main thread event loop are outbrake.
have you used .YieldToNext ?
using preemptive threads should be better.
about database if you access columns by name, access by index could be faster.i guess by name always need to find the index again and again.
Column(“Name")
ColumnAt(Index)
All these situations are inside cooperative threads. The app is around 10 years old. Retrofitting preemptive threads into it is well beyond the realm of practicality. There’s just too much code that needs to be gone through with a fine tooth comb, adding locks to every property access in the app, making sure there’s never a possibility of an exception while a lock is held… it’s just not going to happen.
@William_Yu Can I get a comment on this situation? This performance hit is massive. What does Xojo recommend here? A low priority cooperative thread is about 21x slower than in previous versions of Xojo, and a normal priority thread is about 12x slower. That’s hard to contend with.
Can this be demonstrated in a smaller sample project? That could help us narrow down the problem.
To me, the current behavior is the correct one and xojo finally fixed the cooperative thread priority.
Remember that it is a SINGLE thread pausing main thread and GUI to execute code in the threads then pause that to execute GUI, etc.
It is in fact documented,
Priority:
“These values are totalled, then divided by the main Thread and divvied out by proportion, but the main Thread always has a priority of five, so using very large numbers for other Threads will potentially starve the main Thread. For example, if you give a second Thread a priority of 500, there will be a total 505 slots in the scheduler and five of those belong to the main Thread.
Increasing the value of Priority above 5 gives that Thread more processing cycles than other Threads. Doubling the value of Priority will double the number of processing cycles the Thread gets. A Thread with a Priority of 1 will get one-fifth the processing cycles as the main Thread. The range is 1 to 2^31-1, but very high values of Priority will make it difficult for other Threads to run at all. The value of Priority changes the way in which Threads get processing cycles only if their values are not all equal. … You do not need to use these constants; you can use any legal integer value instead.”
So if you want speed in the code running in the thread you can set its priority to 45 for example, that way the app will spend 90% of the time running the code and only 10% making the gui responsive.
Also if you set a priority to low, the app will waste more time in thread context switching.
Kind of. Results are… weird. They definitely demonstrate a problem, but not at the scale I’m seeing, and don’t always make sense.
Thread Test.zip (4.7 KB)
Tested with priority 1, 5, and 10 in 2023r4 and 2025r2.1. The app computes 1 million SHA3-512 hashes and measures the time.
| Xojo | Priority | Time |
|---|---|---|
| 2023r4 | 1 | 50.68 seconds |
| 2023r4 | 5 | 19.90 seconds |
| 2023r4 | 10 | 18.83 seconds |
| 2025r2.1 | 1 | 98.93 seconds |
| 2025r2.1 | 5 | 28.32 seconds |
| 2025r2.1 | 10 | 38.54 seconds |
Yes, that’s not a mistake, 2025r2.1 at priority 10 was slower than 5. None of 2025r2.1’s times could come close to 2023r4.
Here’s v2 of your app - testing this on macOS with latest Xojo, I’m not seeing anything unusual:
IDE:
Starting tests:
Xojo = 2025r2.1
CPU = macOS 64 bit Arm (IDE Debug)
Start thread with priority = 1
Completed in 12.6 seconds
Start thread with priority = 5
Completed in 11.8 seconds
Start thread with priority = 10
Completed in 11.6 seconds
Built App:
Starting tests:
Xojo = 2025r2.1
CPU = macOS 64 bit Arm (Built App)
Start thread with priority = 1
Completed in 9.7 seconds
Start thread with priority = 5
Completed in 9.3 seconds
Start thread with priority = 10
Completed in 9.4 seconds
However, on Windows, something is definitely amiss:
Here, I’m testing the x86 app on a Windows 11 Arm (Virtual machine).
The app is basically idle: using almost no CPU, with CPU usage mostly sitting at 0%, occasionally spiking up to 3%:
An Arm build for Arm Windows shows the same behavior:
Conclusion: something is wrong with cooperative thread scheduling on Windows, in 2025 R2.1.
Here are the Windows results:
x86 App running on Arm Windows (VM):
Starting tests:
Xojo = 2025r2.1
CPU = Windows 64 bit x86(Built App)
Start thread with priority = 1
Completed in 401.8 seconds
Start thread with priority = 5
Completed in 59.3 seconds
Start thread with priority = 10
Completed in 43.1 seconds
Arm App running on Arm Windows (VM):
Starting tests:
Xojo = 2025r2.1
CPU = Windows 64 bit Arm (Built App)
Start thread with priority = 1
Completed in 141.4 seconds
Start thread with priority = 5
Completed in 18.7 seconds
Start thread with priority = 10
Completed in 13.6 seconds
Summary - In Xojo 2025r2.1…
On macOS, a Thread with priority 1, when it is the only thread running, will still get nearly all the time slices, and the app will hit nearly 100% CPU utilization. This feels like the correct behavior.
On Windows, a Thread with Priority 1, when it is the only thread running, gets very few time slices, and the overall app uses only 2-3% CPU utilization. This feels like a change from prior versions of Xojo, and is most likely a bug.
Thanks. I did forget to mention my tests were in the Windows IDE with default optimization, 32-bit x86.
It works EXACTLY as documented…
Baseline:
- No threads: 18.15
- Preemptive: 18.48
Cooperative threads:
- Priority 95: 18.55 (Sluggish GUI)
- Priority 45: 19.80 (Responsive-ish)
- Priority 25: 20.85 (Responsive)
- Priority 10: 26.07 (Responsive)
- Priority 5: 38.24 (Responsive)
- Priority 1: 215.81 (Responsive)
@William_Yu According with this times, looks like the thread scheduler is way too literal. The main thread keeps all the slots asigned to it even if it has nothing to do.
So, it is working as documented. Even so, is there a way to make it a little more smart so it yields to the other threads if there is not much to do?
Except when it doesn’t.
I’m sorry to pull a “don’t you know who I am” but I used to work for Xojo. I’ve given talks about threading. I do actually know what I’m talking about.

