- From: Chris Wilson <cwilso@google.com>
- Date: Fri, 12 Sep 2014 14:44:33 +0200
- To: Ehsan Akhgari <ehsan@mozilla.com>
- Cc: "public-audio@w3.org" <public-audio@w3.org>
- Message-ID: <CAJK2wqWCZPUdd+W=Sr7bz1Bj35X1n-L_Cuht3TzFxAQ_EeQVKA@mail.gmail.com>
On Thu, Sep 11, 2014 at 6:30 PM, Ehsan Akhgari <ehsan@mozilla.com> wrote: > OK, I think we should remove terminate(). It seems that the exact same > effect can be achieved by AudioNode.disconnect(). > Not entirely; disconnect() does not abort the script and cancel any pending tasks (e.g. setTimeouts, etc.) Terminate is still a valuable thing to do on a worker. Ceasing firing of onaudioprocess is only one of those things. c) How would different AudioWorkerNodes allocated through different >>> AudioContext objects interact with each other? (Here is an example of >>> something that is not clear, should it be allowed to send an AudioParam >>> belonging to a node form context 1 to a worker node from context 2? The >>> spec is currently silent about this.) >>> >> >> You are correct, it in. In general, the spec is silent on how AudioNodes >> created from different AudioContext objects interact with each other. I've >> known this was an issue, but had not ensured that we had an issue filed. >> Now we do: https://github.com/WebAudio/web-audio-api/issues/351. I >> don't think this is specific to Audio Workers. >> > > Hmm. So I'm a bit confused here. I think I remember that the spec used > to prohibit connecting one node from one context to another one from a > different context, so that was what I had in mind when I wrote the above. > But checking the spec again, I don't see a mention of that. Has that > changed in the spec, or is my memory faulty here? > It has not changed in the spec. We need to specify this. No, I don't expect to be able to connect a node from one context to a node from another context (and I also don't expect that audio workers in different contexts to be in the same thread or communicate with each other; but it's not observable anyway). I do expect we should be able to share AudioBuffers across threads, though. e) What is the order in which these worker nodes receive the audioprocess >>> events (assuming obviously that one such node is not an indirect >>> input/output of the other)? Note that with the currently specified API, I >>> think it is possible for one of these workers to send a MessagePort through >>> the main thread to another one, and therefore be able to communicate with >>> the other AudioWorkerNode workers through MessagePort.postMessage, so the >>> order of execution is observable to script. (I admit that I don't have a >>> good solution for this -- but I also don't know what use cases for >>> transferring information back and forth between these nodes and the main >>> thread we're trying to address here.) >>> >> >> I don't think this is true; MessagePort is asynchronous, and the firing >> of onaudioprocess events would be synchronous (more to the point, the >> system would, I expect, resolve the entire audio graph for a block before >> processing messages). I don't expect Audio Workers to communicate with >> each other, and I don't believe they can observe each others' behavior. >> > > I'm not sure what you mean by MessagePort being asynchronous. Obviously, > MessagePort.postMessage() is an asynchronous operation (I think that's what > you meant, please correct me if I'm wrong.) What you describe above is my > understanding of the intention as well, but I don't think that's currently > specified. > MessagePort.postMessage is asynchronous. That makes any observation of ordering you could do through communicating with another Audio Worker through a MessagePort irrelevant; its timing would not let you detect which is processed first, for example. Or am I misunderstanding how you would use MessagePort? > 2. I feel very strongly against exposing this node type as a web worker. >>> I think that has a number of undesired side effects. Here are some >>> examples: >>> >>> a) Even though the HTML web worker termination algorithm says nothing >>> about killing an underlying worker thread, I think that is what authors >>> would typically expect to happen, but obviously doing that would not be an >>> option here. It is also not specified what needs to be output from the >>> node after terminate() has been called on it (the input unmodified? >>> silence? something else?) Also, given the fact that you can already >>> disconnect the node from the graph, why do we need the terminate() method >>> in the first place? >>> >> >> I'm not sure why that's not an option, and the terminate() description >> DOES say the worker thread should be terminated. (not the underlying >> system thread, but that's not intended.) As Alex said, terminate() is >> there for uniformity with Workers, and for clarity in enforcing "no more >> onaudioprocess events, please." >> > > That effect can be achieved by just disconnecting the node. > See above. disconnecting will not halt other processing the audio worker might be doing. > b) The API gives you the illusion that multiple AudioWorkerNode's will run >>> on different DedicatedWorkerScopes. That, in Web Workers world, would mean >>> different threads, but that will not be the case here. I think that >>> discrepancy is problematic. >>> >> >> Why? >> > > Honestly I can't quite imagine how authors would perceive this. Here is > an example: do you think it's unreasonable for an author to expect that > worker nodes on the same audio context use the same global object? The > answer to that question is observable to script. > Yes, I think it's unreasonable for an author to expect that worker nodes would share a global object. The global object contains the onaudioprocess event handler; it has a one-to-one correspondence with a single node. It HAS to. Node implementations cannot share data (except through the main thread, or possibly through a sub-shared worker. > c) Using DedicatedWorkerGlobalScope is a bit weird in terms of APIs that >>> are exposed to workers. For example, should these workers support >>> onlanguagechange? What about IndexedDB on workers? What about nested Web >>> Workers? >>> >> >> Yes, I would think they would support these. Particularly nested Web >> Workers, e.g. >> > > What is the use case in supporting these? > Creating worker threads to do multi-threaded audio processing (introducing latency, of course, to get the data across thread boundaries). This has already been requested. > d) At least on Gecko, Web Workers have specific implementation concerns in >>> terms of their message queue, event processing model and so on. It might >>> be a lot of effort for us to properly implement the observable behavior of >>> these workers running inside our audio processing thread code (which has a >>> completely different event processing model, etc.) >>> >> >> That's the point of having this discussion, yes. >> >> >>> e) The topic of whether or not synchronous APIs must be allowed on >>> workers is being debated on public-script-coord, and it seems like there is >>> no consensus on that yet. But I find the possibility of running >>> synchronous XHR on the audio processing thread unacceptable for example, >>> given its realtime requirements. >>> >> >> Of course. That (using synchronous XHR) would be a dumb thing to do. So >> would "while (true) ;". >> > > Well, labeling these concerns as dumb doesn't really address the issue. I > agree with you completely that those are dumb, but the point is that we're > making them possible, so we should be thinking very hard about the > consequences of that. There is always a chance of people doing these > things. > Yees; but that's precisely my point. People can "while (true) ;" today. This isn't new, it isn't unique to using workers or even being in the audio thread; in practical terms, I'm not convinced it would be any better to have a constantly-glitching ScriptProcessor in the main thread (because it's CPU-starved) than to not be able to service the whole audio graph due to a CPU-starved Audio Worker. I think they end up being pretty functionally equivalent. > I think tying this node to Web Workers opens a huge can of worms. It will >>> also keep biting us in the future as more and more APIs are exposed to >>> workers. I am wondering if we can get away with a completely different API >>> that only tries to facilitate the things that authors would typically need >>> to do during audio processing without attempting to make that a Web Worker? >>> >> >> Only by using some other language to represent an "audio shader", and >> having that language runtime run in the audio thread. Anything else would >> add inherent latency, which would destroy the ability of this to >> self-describe Web Audio. >> > > Is inventing a new language really our only alternative? I don't think > so. Another option is to run these workers under a restricted and new > global object that exposed built-in Ecmascript objects, and expose any > additional APIs that addresses a use case that makes sense to audio > processing. > What do you think is in Workers that won't be needed in audio workers? In looking through the list, I'd say pretty much everything could be interesting. > 3. What is the purpose of addParameter and removeParameter? It seems to >>> me that if we defined a structured clone algorithm for AudioParam (which is >>> another detail missing from the spec that needs to be clarified anyway) and >>> make it transferable, then the author would be able to postMessage() an >>> AudioParam just as easily. Is there a good reason to have a specialized >>> method for what is effectively posting an AudioParam to the worker? (Note >>> that we'd probably need to add methods to AudioParam for extracting a-rate >>> and k-rate values at any given time in that case, so that the worker script >>> can get the right values when it needs them.) >>> >> >> No. To have AudioParams be connectable (i.e. connect an Oscillator into >> an AudioParam) with zero latency, they must be evaluated in the audio >> thread, only in the current block, only when they are needed. You can't >> extract ahead of time, or ask for them later; their value buffers need to >> be handed to the onaudioprocess when it fires. >> > > That's exctly what I meant. I was not suggesting adding methods for > arbitrarily peeking into the AudioParam values from the main thread. > > (Note that my suggestion may mean exposing these objects through another > interface to the worker.) > I'm confused. This sounds, then, precisely like what the Audio Worker exposes (the parameters object's arrays described at http://webaudio.github.io/web-audio-api/#widl-AudioProcessEvent-parameters ). > 4. More on the idea of transferring an AudioParam to a worker, that will >>> probably involve some kind of neutering the object. It might make sense to >>> introduce a clone() method on AudioParam as a way for authors to be able to >>> keep a copy of the object around on the main thread. That could of course >>> be a future enhancement idea. >>> >> >> In essence, the design of AudioParams here is much like AudioNodes >> themselves - one part sits in the main thread, one part sits in the audio >> thread. The latter does the heavy lifting. >> > > Well, my point was more towards the state that is stored inside the > AudioParam (namely the automation events.) We need to specify what happens > if you hand off an AudioParam to a worker, and then add or remove an > automation event to/from it after that. > What do you mean by automation events? The audio processing system knows how to create a value array from an AudioParam with its connected inputs and any schedule events; it hands those value arrays to the onaudioprocess handler. 5. Still more on the idea of transferring an AudioParam, another thing that >>> we need to worry about is what happens if you try to transfer an AudioParam >>> that is currently being used somehow (either through being a property on >>> another AudioNode, or being used as an input to one.) >>> >> >> How would you make such a transfer? >> > > Through addParameter? > That's not a transfer; you can only create another parameter. addParameter takes a name, not another AudioParam.
Received on Friday, 12 September 2014 12:50:33 UTC