ValueTrees Call Garbage Collection From RT Thread

So – obviously we shouldn’t be grabbing properties out of value trees on every callback – but occasionally I need to check a property or two here or there. Most of the time I make an identifier to speed it up, but just found something quite cryptic.

I had some hard to track down random CPU spikes in my app, after digging for awhile I found it was due to:

This appears to sometimes occur from my audio thread if it’s the place that grabs a fresh value from the tree. (sometimes I need to get a value from somewhere else in the app and I don’t have a cached value or identifier for it)

So – not much an issue but, wouldn’t it make sense for JUCE to always defer this garbage collection to the message thread out of the box? I.E. – could we wrap this entire thing in a && isMessageThread()?

Seems it would reduce the chance of undesirable behavior quite a bit.

I think this implementation is fine, because ValueTrees were never designed to be used from a realtime thread. I think of them as explicitly “message thread objects”.

What do you do for stuff which doesn’t have any automagical binding you always setup a cached value?

I agree they typically are, but I still don’t think they should construct an identifierperform garbage collection in a non deterministic way.

Well, it’s kind of a QoL feature from JUCE, that strings and identifiers are managed safe and fast. It’s just not designed to be used for real-time or for processor-close code.
I feel like you’ll have to make the message thread push updates into your real-time accessible cache to make sure you know what is going on.

It’s very easy with the Snapshot Source from Palmer Hogan shown at ADC23

It’s not a critical issue for me it’s solved now, but I think everyone on this forum would have a lot of money if they got a dollar for every time a new user posted code they need help with that used a valuetree in the RT thread.

We’re all sitting here saying, “this should be on the message thread” and agreeing, yet I myself after many years working with JUCE, wasn’t aware of this. I just thought they were slow.

So people will do it have no idea why they’re getting CPU spikes, and for beginners it’s not a few hours to find it’s probably months or maybe never. Just some feedback!

1 Like

How are you creating your identifier? If you make them const static they shouldn’t affect the StringPool as they’re passed to the ValueTree functions by reference.

2 Likes

Yeah – I swapped the area I found the issue with const identifiers and it solved the problem.

My concern is just that’s it’s quite a large codebase, and I often have students and less senior engineers working with me, and it’s a pretty easy / harmless mistake to make.

It might just edit our instance of JUCE to only call the garbage collection if it’s the message thread.

Yes, for situations like that I just have a listener that listens to changes and stores the value in an atomic.

Non-atomic values (arrays, etc) would have race conditions if you’re trying to read them in the RT thread anyway, so you need a better way to pass the values down the processor following changes, using a FIFO, a SpinLock, etc.