Improve threading for main thread?

Hello,

when 4 threads run, they get about 25% of CPU time each.

I can set priority to 1 for each.
But how can I give main thread more priority and make sure Xojo does the run loop each time on main thread, before switching to a thread?

instead of looping over

  • Main
  • Thread A
  • Thread B
  • Thread C
  • Thread D

work like this:

  • Main
  • Thread A
  • Main
  • Thread B
  • Main
  • Thread C
  • Main
  • Thread D

as input on keyboard is lacking here.
Greetings
Christian

Thread priorities are added together then apportioned
See http://documentation.xojo.com/api/language/thread.html about Priority
The main thread has a NormalPriority (of 5)
I dont know if you can boost its priority by getting a reference to it then adjusting it (cant say I have ever tried that although the docs say it ALWAYS has a priority of 5)
But if you have enough priority 1 threads then the main threads 5 isnt sufficient to make it get run as you indicate
Short of having the other threads sleep themselves not sure what else you can do to force the main thread to run as frequently as you want

Even then, I doubt it will do what you hope. What I expect would happen is something like this:

  • Main loops x times
  • Thread A loops 1 time
  • Thread B loops 1 time
  • Thread C loops 1 time
  • Thread D loops 1 time
  • Main loops x times
  • (etc.)

Instead, you can store in a global property somewhere App.CurrentThread. Each Thread would store its own value in that property and, when it changes, it would first execute the common code you want it to execute.

if you use Sleep with some millisecs in the Run Loop of a Thread the Main got more Time, at least i experienced with one thread beside.
otherwise i found
Application.YieldToNextThread
Application.SleepCurrentThread

I’ll add some context here, since this question is based on a question I asked Christian. I’m using CURLSMBS to http requests, and PerformMT inside a thread so that the request does not lock up the whole app. What I’ve noticed is that most of the time, this works fine, as requests are quick. But if there is a reason the request cannot complete, waiting for the timeout to elapse absolutely tanks performance with even a single thread/request going. I was asking if PerformMT could yield more time, or perhaps only get more aggressive once a connection is established.

He pointed me to this thread. Part of his reply was [quote]I have a delay 1 milli second in the CURL thread waiting and if I remove that, we need 98% on a core and it’s not faster.[/quote]

Now that I think about it, I think this is the opposite of what would need to happen. Increasing the delay, not removing it, should yield more time to other threads, right? I’m not a plugin or C developer, so I’m not certain.

assuming the delay yields and isnt just a tight busy loop I would think increasing the delay would yield more time to other threads
but I know nothing about how CURLMBS implements this

Xojo threading is cooperative.
Our threads loop like this:

while not done Yield to Xojo Sleep 1ms wend

And the 4 threads do get pretty much time passed from Xojo. Not sure how to tell Xojo to only come back to each thread every few ms. If I remove the delay, I get close to 100% CPU time.

yeah you would under that scenario

maybe u can use Pause/Resume

I think I’d just prefer a setting for the amount of sleep time, so that I can sacrifice curl performance for main thread performance. I’d probably use 10ms instead of 1ms.

would be nice if there was a mechanism where a thread like CURL can be spun off into an actual p-thread and then when its done reattached to the running Xojo thread pool and join back in Xojo’s threading

you know
like this <https://xojo.com/issue/58144>

That doesn’t help. that means the cooperative thread sleeps 10ms and with it the whole app!

What we need is that Xojo runs main loop before thread to keep the main loop more responsive.
Maybe tomorrow I can make a test project to verify that the behavior is like we say with some counters.

1 Like

Ah… ok.

This is a perfect example of why I use Shells and wait loops (or IPC if communication aside from stdin/stdout are needed) for thread handling - let the system deal with it instead fo the Xojo framework. I learned that trick years ago. This is why the old Task class made my apps a gazillion times more responsive - both in the UI and in the external tasks.

Launch CURL in a Shell in a Thread.

Do myCURLSh.poll Me.Sleep 10 // handle message display ... Loop Until Not myCURLSh.Is Running

We’ll see whether Christian can work out some kind of miracle, but I have a feeling I’m going to have to decide between the reliable yet performance gobbling CURLSMBS class, or the unreliable but friendly URLConnection.

I think you may solve this by doing the asynchronous mode.
See CURLSMultiMBS class, where you can add CURLSMBS and then run a timer with 10ms or so delay and call Perform on it.
When a CURLSMBS is finished, it raises the TransferFinished event on CURLSMultiMBS and Finished event in CURLSMBS, so you can process result there.

CURLSMultiMBS doesn’t crash as often as URLConnection. For downloading multiple files the multi is great.

CURLSMultiMBS was made to handle dozens of parallel transactions efficiently on the main thread from a timer.
PerformMT was made to put a transaction on a preemptive thread, so a synchronous lookup function for DNS doesn’t block your main app.

Do you add #pragma DisableBackgroundTasks ? If not, then the thread will yield three times - once at the While loop, once at the Yield, and once at the Sleep. This may complicate issues.

This is in C++ and I call yield function there on purpose.