Closed asilvas closed 2 years ago
Atomics.wait
isn't generally real-time safe, so not really. What's the use-case?
Polling is generally a lot more efficient than other techniques, because there's already something that is called repeatedly (render loop, decoding loop, AudioWorkletProcessor.process
, etc.), using a system call to wake up a sleeping thread is a waste of time.
This is for nodejs where a dedicated thread is waiting for more work off the ring buffer. Using hard polling is very CPU intensive.
It sounds to me that you're not looking for a wait-free queue, right? Clearly you want to wait, and you're not in a real-time scenario? Is postMessage
or waiting on another bit of memory with wait
/notify
or something like that not good enough? Wrapping this SPSC ring buffer in something else that provides the wait
/notify
might be the right design here.
This is a real-time scenario. Performance implementations of ring buffers don't typically rely on hard polling as it's very wasteful on resources. I can look into exposing in a different package if it's not something you're interested in supporting.
Well, a real-time safe data structure can't use wait
or notify
either, as this ends up potentially doing system calls. wait
isn't available in, say AudioWorkletGlobalScope
anyway, which is the only way to get a real-time thread on the web, and notify
takes a lock (spidermonkey, v8), so it cannot be used in wait-free code.
What kind of real-time are we talking here? This package has been originally written for hard-real-time, low latency audio processing scenario on the Web, where one thread is running in a different scheduling class, and other threads either provide or consume data from/to it, and the real-time thread can never block. Those types of ring buffer usually never have notify
/wait
primitives (here are a few I know of, mostly in rust, C++ or C, in use in various projects already: https://docs.rs/rtrb/latest/rtrb/, https://libcinder.org/docs/classcinder_1_1audio_1_1dsp_1_1_ring_buffer_t.html, https://www.boost.org/doc/libs/1_63_0/doc/html/boost/lockfree/spsc_queue.html, https://github.com/jackaudio/jack2/blob/852ba2b8ebc944865e75d8eb5d4550d408772f3b/common/jack/ringbuffer.h, https://searchfox.org/mozilla-central/source/mfbt/SPSCQueue.h, http://files.portaudio.com/docs/v19-doxydocs-dev/pa__ringbuffer_8c.html).
But real-time is a spectrum, other use-cases might be softer than that. It would be very useful to have something that sits on top of this queue (it can be made efficient since the memory is passed as an argument, cache wise), and provide nicer synchronization, e.g. with notify
/wait
(when available), or some sort of futex. But it's probably not possible to write a good futex at the moment at least on the web, lack of synchronous sleep or access to the proper intrinsic, or an equivalent of sched_yield
. Maybe node has those, do you know?
I understand now this package was designed for web so I'll move on. My background on this topic is with POSIX so I'll investigate the low levels more in node/v8 to determine the feasibility/tradeoffs of leveraging notify/wait. Long story short, I have many threads processing commands and I don't want those threads each consuming 100% of each CPU core. My current implementation leverages postMessage
(which works well) but even with efficient v8 serialization there is still considerable overhead for real-time software, thus why I'm looking into leveraging ring buffers for many-to-many thread communication. Thanks for taking the time!
I wonder if it's possible to port one of the moderne work-stealing queue algorithms in the current state of nodejs' ecosystem, that would probably be the best you can do (not knowing too much about the problem though).
Howdy, cool project! Curious if you have any plans to support signaling via
Atomics.wait
to avoid the need for hard polling?