Max JS Threading Priority... Should I Care?

According to the Max docs, all js logic executes on the low-priority thread.

The two threads allow you to use Max to do things that require high timing accuracy (such as MIDI) at the same time as you do things that are computationally expensive (such as decompress video) or involve user input.

By default, the js object executes all Javascript code in the low-priority thread. In particular, if it finds itself running in the high-priority thread, it will defer execution of whatever it was supposed to do to the low-priority thread.

Is this hitting anyone in practice?

I’m doing some timing-sensitive patches and I think I’m coming up against it but curious if it’s a bugaboo.

Cheers and thanks in advance!

Interesting how silent the cycling74 folks are on a thread where this is discussed:

Also interesting how the ability to specify execution on the high priority thread (e.g., via immediate) was deprecated as of Max 6. Wonder what the backstory is there. And also whether this breaks any assumptions for monome patches that were baked with JS in the Max 5 days?

the way i’ve been using js in max is basically to embed the whole application and use other max objects very sparingly-- ie, OSC communication for i/o and sound/MIDI on the output side. so i’m likely never encountering priority issues.

it might be worth raising the question on the cycling forum again.

Thanks @tehn!

I’m thinking for what I’m after in this case a proper C external is probably the ticket since I’m looking at a lot of traffic in and out of my abstractions, exactly where a priority mismatch would like matter most.

It’s too bad though since the lack of immediate is a real gotcha for JS in Max. I’ll brave the cycling forum in a bit and report back if I learn anything interesting.


1 Like

caveat: i haven’t used max much in a long time, like since version 5 (when immediate was introduced, iirc), and mostly on version 4.5. but these were topics of interest then, when mxj and js were new (and, unfortunately many of the c74 articles on the topic seem to be dated from that era.) but i did have to do some max 7 work for a gig recently and had some contact with these issues (receiving lots of soft-realtime network data in max, with some js in the patch.)

so, fwiw…

maybe, maybe not. at least one form of priority inversion was possible in max 5 even when using immediate. the example from that article: if you have something coming off the high-priority thread (like a MIDI note) and you even just pass it through a message box before sending it into js, then your javascript function using it will be deferred to the queue even if it is declared immediate, because UI events have to happen on the queue. but if literally none of your inputs to js come from UI elements, then yeah you’re probably right.

iirc, the best way to ensure that javascript executes on the high-priority thread is to wrap it in a Task object. [nah, i take it back… callbacks still go on the queue. sorry.]

for general information on the threading model in Max, seems like the most up-to-date place to look is the max 7 SDK docs, particularly the chapters on threading, scheduler and low-priority queue.

if you haven’t checked it out, this article is also important (though dated, referring to the state of affairs in 4.5.)

it doesn’t really surprise me that immediate is deprecated, since a) it can be misleading as mentioned above, and b) i can imagine that it could easily lead to deadlocks for other things on the high-priority thread, if it’s not simply ignored (API was free to do this; it can even defer stuff from C externals), and c) who knows! keeping up to date with multithreading best-practices is hard enough without throwing a javascript engine in the mix.

anyway, long story short, worth considering just writing a C external if you are really concerned about having control over timing (i.e., want to be free to shoot yourself in the foot :slight_smile: ), and your code is primarily concerned with processing realtime events. it’s not the worst API to work with.

another option is to just not worry about it until and unless you run into issues that are pretty definitely attributable to starvation of the low-priority thread. i guess it’s more likely if your patch is doing a lot of heavy lifting in other areas that are always low-priority; particularly manipulating jitter matrices.