startRealtimeThread examples

Hi guys,

I’m testing JUCE 7 with the new thread priority system. How startRealtimeThread should work?
Should I always try to guess the run() execution time?


That wouldn’t make any sense, since that would be bound by the runtime of the program, which you cannot guess. The run method is called once and when the method exits, the thread is dead. If you want to keep it running, you need to loop.

I also find it hard to come up with the number that is expected there and why this is of any concern. Is that the maximum amount of time of a possible loop? Is that the amount of time per average possible loop cycle (and keep in mind, that is the average) or is that the amount of time expected to sleep between loop cycles (which couldn’t be guessed, since it depends on the time one possible loop cycle needed). Also, how to tell the system that a loop cycle wants to start / has finished?

I’m just trying to figure out the sense of the new RealTimeOptions required to create a real time thread.

As far as I understand, the workDurationMs value is required. I need to be sure that the thread I’m running is placed on a Performance core.


Ah ok, that clears up at least my questions. And the question, why that is not documented in the web interface xD (I think that’s a typo that there is a “*” missing).

But that just raises more questions and concerns. First of all, does that mean that the Thread object now behaves different on macOS vs all other OS? Up until now I was pretty sure, that “run” is called once and when you exit your thread is done. This is also how I would interpret the documentation of the run method.
Also, workDurationMs only works if all threads (including the main audio thread) are started at the same time? - which you cannot guarantee. You can’t even be certain, that your own threads are all started at the same time. So what could end up happening, is that your thread is wasting the first few ms in his run method waiting the main audio thread to be called (meaning it is go time with the new MIDI data and stuff) and then start processing which might result pretty regularly in overrunning the workDuration.

But the way you would calculate this value is (blockSize/sampleRate)*1000. That would be the real time constrain in which the audio device is expecting you to deliver data (in ms).

By profiling the operations done in the run() method of my thread, it takes around 3ms to complete, while calculating the block time (as you pointed out) should require, in the worst case, 46ms (44.1 @ 2048)

I’ve used a workDuration of 20ms as a test value. the thread runs better than when I was on JUCE 6.1.5, where it was jumping between E and P cores, while now is placed steadily on E cores. I’m wondering if there’s a way to control this behavior and make a selected thread running on P cores.

I agree.

It’s an annoying requirement for macOS and real-time threads in general but its par for the course when it comes to ‘real-time’, It generally assumes you’re running deterministic algorithms in your code block.

@lcapozzi Core assignment isn’t always black and white. macOS really tries to be power efficient and its heurstics might have determined it can safely schedule your code on an E core. If you were to apply some load to the other cores or artificially do some heavy lifting in your code, you might see it behave differently.

A grain of salt however, as this is mostly speculation from my tinkering. I would assume different behaviour on the different M1-2 variants (M1 ultra has fewer E cores but they’re clocked faster etc).

On the flip side, the newer Intel CPU’s have way more E cores than P cores so, an API that forces code to run on E/P cores might not make the most sense when dealing with multiple platforms.

Hi @oli1 and thanks for clarifying. Right now it’s already a progress that my thread has stopped jumping between cores, so maybe that should work. At this point I’m wondering if moving my convolution threads to real time or just to Priority::highest. Realtime is working fine for the pitch detector thread.

I usually use normal threads for heavy lifting and the audio/real-time threads for copying the audio around. FIFOs are my go-to for sharing data.