Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why AudioWorklet disables Atomics.wait? #1848

Closed
orange4glace opened this issue Apr 4, 2019 · 3 comments
Closed

Why AudioWorklet disables Atomics.wait? #1848

orange4glace opened this issue Apr 4, 2019 · 3 comments

Comments

@orange4glace
Copy link

orange4glace commented Apr 4, 2019

I didn't test on other browser but only Chrome and it might only matter on Chrome.

As AudioWorklet SharedArrayBuffer model example shows, a separate Worker thread produce audio data and AudioWorklet thread consumes the produced data continuously.
But this sample code has race condition issue when producing audio data on Worker thread takes heavy time for some reason and Worklet thread tries to consume before the data is produced.
Which means Worklet should check whether data is ready or not. Two possible solutions are (as written on here

  1. Send message when output buffer is ready via MessagePort
  2. Block AWP until output buffer is ready (Atomics.compareExchange or spin-lock)

But both of them seems to have a problem.

  1. Main UI thread must get involved as a relay in message passing between AWP and DWG. As a result, there might be a delay issue when UI thread is kinda busy.
  2. Performance issue

Glitching is not a problem in here since glitching has already happened when consumer suffers lack of data. Rather than, this such unnatural solution to solve this situation makes me feel bad. If Atomics.wait can be used in Worklet thread, it can just wait using Atomics.wait until data is ready and everything will looks fine.

Or, is there any technical / design issue which prevents Atomics.wait to be enabled on AudioWorklet?

@hoch
Copy link
Member

hoch commented Apr 4, 2019

By design, AudioWorkletProcessor must be synchronously processed by "rendering thread". If the user code in the processor blocks the thread (like Atomics.wait), it will stall the entire graph rendering loop affecting the other processors' progress. That's why AudioWorkletGlobalScope does not have Atomics.wait.

For real-time audio use case, synchronously blocking the thread is generally not a good idea. I'll update my example with a better shared memory model.

@padenot
Copy link
Member

padenot commented Apr 11, 2019

http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing is the classic reference for this kind of question, but the bottom line is: one should never ever ever wait in a real-time audio callback, so we disabled Atomic.wait, because there is no good reason to have it, and not having it clearly sends a message to authors, they if they are trying to wait on anything, they are doing something wrong (of course they can busy-wait, etc., it's not foolproof).

@kawogi
Copy link

kawogi commented Aug 25, 2022

Does this also apply to the WASM instruction memory.atomic.wait? Then it might be impossible/impractical to use muti-threaded code in a worklet at all. Even the compilation of an empty Rust program emits those commands an I'd guess a lot of library code (Mutex, Memory management, …) will do this as well.
Speaking for me: I'd rather experience an audible glitch than having my program crash randomly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants