Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 6:41 PM, Jonas Sicking wrote: > On Thu, Nov 17, 2011 at 6:05 PM, David Levin wrote: > > > > > > On Thu, Nov 17, 2011 at 5:05 PM, Jonas Sicking wrote: > >> > >> On Thu, Nov 17, 2011 at 2:07 PM, David Levin > wrote: > >> > It seems like this mechanism would deadlock a worker if two workers > send > >> > each other a synchronous message. > >> > >> Indeed. We can only allow child workers to block on parent workers. > >> Never the other way around. > > > > So the api would have to know who is listening to the other end of the > port > > and throw if it isn't a parent? > > I'm not convinced that we can do this with ports in a sane manner. > Only on dedicated workers. There you always know who is listening on > the other end. I.e. only on the DedicatedWorkerGlobalScope/Worker > interfaces. Ah so the proposal is really only adding a new method only on DedicatedWorkerGlobalScope which send a synchronous message and something corresponding on Worker which can respond to this. This proposal as you see it does nothing for port or shared workers. That seems to make more sense now. dave
Re: Opening discussion on StreamWorker
On 11/17/2011 4:52 PM, Charles Pritchard wrote: Currently, Web Workers provides a "heavy" scope for multithreaded Web Apps to handle heavy data processing. I'd like to draw on those specs and create a new lightweight scope useful for various data processing tasks typically associated with stream processing and GPUs. CSS/FX is looking at custom filter tags using WebGL. I think we can implement these in Workers as well. The most important constraints are that the data is opaque: no shared storage allowed. There are many examples of using web workers to apply effects to 32bit pixel data. Those could be easily applied to CSS pixel filters just as WebGL shaders are. River Trail and W16 are showing us ways in which tight for loops can take advantage of multiple cores. Let's look at these use cases and consider a new lightweight worker scope. Nothing but the bare bones, designed and expected to be used for a very specific type of task. Existing CanvasPixelArray processing scripts are a great place to start. I suspect we'll be able to handle other cases, such as stream ciphers. I'm still trying to bikeshed a name on this... StreamWorker, OpaqueWorker, SimpleWorker, DataWorker etc. Please join me in the discussion. I think we can make rapid progress here now that Transferable has matured and we have two moderately-parallel JS implementations. To be more clear: here is some in-the-wild code that is similar to what I'd expect to produce and consume with StreamWorker: http://code.google.com/p/chromabrush/source/browse/frontend/js/filter.blur.js Pseudo-code: onmessage(data) { for(... data) { data[i] *= fancyness; }; postMessage(data); }; In doing this, could attach to CSS such as: img { filter: custom(url('basicpixelworker.js')); }. The worker may only use postMessage once, and it must send back an array of the same size. There are no other options, no ways to pass a message to other contexts, no File or IDB or other APIs. The concept here is to be very restrictive. That way, no data is leaked, and it behaves more like a WebGL shader (think GPGPU) than our existing web worker context. If it's rigid, we can get very good performance, high parallelism, and modularity. We can also get quick implementation from vendors. And they can decide when they want to optimize. As a completely different use case, such a simple worker could provide stream encryption, or perhaps some other kind of basic but heavy number crunching. Since it's just a simple in-out routine, it can be highly optimized and easily added into API pipelines. These workers would still be backward compatible. They could still be used as normal web workers. But in their more basic state, they can be more lightweight, there are no side effects and so they are more appropriate for massive parallelism. -Charles
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 8:05 PM, Jonas Sicking wrote: > On Thu, Nov 17, 2011 at 2:07 PM, David Levin wrote: > > It seems like this mechanism would deadlock a worker if two workers send > > each other a synchronous message. > > Indeed. We can only allow child workers to block on parent workers. > Never the other way around. > Note that the port entangled with the port you're waiting on might be transferred between workers while you're waiting on it, changing hands from a parent worker to a child worker. It might be a valid port to block on when you make the call, and stop being valid later. I'm still thinking about this, but one note is that this isn't needed for the polling case (where timeout is 0). -- Glenn Maynard
Re: Synchronous postMessage for Workers?
On Nov 17, 2011, at 6:41 PM, Jonas Sicking wrote: > On Thu, Nov 17, 2011 at 6:05 PM, David Levin wrote: >> >> >> On Thu, Nov 17, 2011 at 5:05 PM, Jonas Sicking wrote: >>> >>> On Thu, Nov 17, 2011 at 2:07 PM, David Levin wrote: It seems like this mechanism would deadlock a worker if two workers send each other a synchronous message. >>> >>> Indeed. We can only allow child workers to block on parent workers. >>> Never the other way around. >> >> So the api would have to know who is listening to the other end of the port >> and throw if it isn't a parent? > > I'm not convinced that we can do this with ports in a sane manner. > Only on dedicated workers. There you always know who is listening on > the other end. I.e. only on the DedicatedWorkerGlobalScope/Worker > interfaces. I agree on this one. A big no-thanks to synchronous messaging over ports. Still, dedicated workers to a parent seems doable. I've proposed a different worker scope for lightweight threads. Dedicated workers are relatively heavy and so a few workers blocked on the parent is not outside of acceptability. -Charles
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 6:05 PM, David Levin wrote: > > > On Thu, Nov 17, 2011 at 5:05 PM, Jonas Sicking wrote: >> >> On Thu, Nov 17, 2011 at 2:07 PM, David Levin wrote: >> > It seems like this mechanism would deadlock a worker if two workers send >> > each other a synchronous message. >> >> Indeed. We can only allow child workers to block on parent workers. >> Never the other way around. > > So the api would have to know who is listening to the other end of the port > and throw if it isn't a parent? I'm not convinced that we can do this with ports in a sane manner. Only on dedicated workers. There you always know who is listening on the other end. I.e. only on the DedicatedWorkerGlobalScope/Worker interfaces. / Jonas
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 5:05 PM, Jonas Sicking wrote: > On Thu, Nov 17, 2011 at 2:07 PM, David Levin wrote: > > It seems like this mechanism would deadlock a worker if two workers send > > each other a synchronous message. > > Indeed. We can only allow child workers to block on parent workers. > Never the other way around. > So the api would have to know who is listening to the other end of the port and throw if it isn't a parent? dave
Re: Web Messaging Intents, was: Re: [DRAFT] Web Intents Task Force Charter
On Mon, Nov 14, 2011 at 7:24 PM, Charles Pritchard wrote: > ** > Does anybody use registerProtocolHandler in any real sense? Is > registerContentHandler needed? It seems like Web Intents is an evolution on > the concept. I don't think we're going to see convergence on those old > methods. I'm ready to leave them both in favor of a yet-to-be announced > candidate (web intents). > > URIs are better than protocols, and Intents are better than content > handlers. In my opinion. > RPH seems to be intended primarily for mailto: (I think that's where it is used.) I'm not sure what the RCH usage is like. It is definitely possible to imagine mapping UA handling of mailto: onto web intents. The way I think of it is like this: RPH is basically an action with a payload. RCH is essentially type info with the payload. Web Intents is kind of off-axis with both an action and a type as well as the payload. The idea (taking inspiration from the pluggable usage in the Android ecosystem) is that the action (analogous to the "protocol") is a locus between the client and handling service which can be messaged to the user in a well-understood way. (i.e. instead of just saying "here's some data, do whatever you want with it," which is a more content-type-driven As far as I can tell, the model doesn't prohibit, nor does it encourage, > the passing of MessageChannel. > It's very much made for an RPC style of communication, but if the message > being passed back is a channel, well that's just fine. > > Am I mistaken? What I'm seeing is that we get MessageChannel for free, and > there's no need to specify further. > Individual Intent authors can do that themselves. > Yes. We envision RPC-style request/response as the sweet spot for intents. We've definitely considered use cases which are better served by opening a persistent channel. It isn't clear to me as yet what to do about those. They definitely imply a more well-specified protocol to be pursued over that channel. Web Intents as an API doesn't really include or exclude that in the current form. On the other hand, it'd be a really nice application of the Web Intents permissions mechanism to be able to connect up, say, an SSH connection using Web Intents, so that I could write an in-browser terminal which could then be attached to a secure socket by the user. At this point, I'm not sure whether this kind of persistent connection use case is far enough from Web Intents to want to exclude it, or close enough to want to include it explicitly. Our early belief is that we aren't ruling it out with the proposed API, since MessageChannels could be provided or returned in the payload data. On the other hand, we haven't chosen to explicitly include such usage. But a lot of this stuff just comes with nice platform integration; I just tried passing Blob objects through intents in Chrome Tip-of-Tree with our prototype, and it Just Works, allowing a really appealing vision into what "upload" intents and file interactions could be like. Wins like that make me think that focusing on the sweet spot RPC interaction will not paint us into a corner. -Greg
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 2:07 PM, David Levin wrote: > It seems like this mechanism would deadlock a worker if two workers send > each other a synchronous message. Indeed. We can only allow child workers to block on parent workers. Never the other way around. I think in theory it would be possible to reverse the direction for given parent/child pairs, but I'm not yet sure that that couldn't lead to deadlocks. And I'm definitely not sure it's worth the complexity. / Jonas
Opening discussion on StreamWorker
Currently, Web Workers provides a "heavy" scope for multithreaded Web Apps to handle heavy data processing. I'd like to draw on those specs and create a new lightweight scope useful for various data processing tasks typically associated with stream processing and GPUs. CSS/FX is looking at custom filter tags using WebGL. I think we can implement these in Workers as well. The most important constraints are that the data is opaque: no shared storage allowed. There are many examples of using web workers to apply effects to 32bit pixel data. Those could be easily applied to CSS pixel filters just as WebGL shaders are. River Trail and W16 are showing us ways in which tight for loops can take advantage of multiple cores. Let's look at these use cases and consider a new lightweight worker scope. Nothing but the bare bones, designed and expected to be used for a very specific type of task. Existing CanvasPixelArray processing scripts are a great place to start. I suspect we'll be able to handle other cases, such as stream ciphers. I'm still trying to bikeshed a name on this... StreamWorker, OpaqueWorker, SimpleWorker, DataWorker etc. Please join me in the discussion. I think we can make rapid progress here now that Transferable has matured and we have two moderately-parallel JS implementations. -Charles
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 6:50 PM, Glenn Maynard wrote: > On Thu, Nov 17, 2011 at 6:17 PM, Rick Waldron wrote: > >> No, it's not. Messaging should not block either process. >> > > No, it's perfectly fine to block a worker, as long as the worker > explicitly requests it and is expecting it. > > I don't know what that means. Synchronous APIs are one of the major >> reasons to have Workers in the first place. >> >> Considering the current messaging API and the allowed host APIs, I >> strongly disagree. >> > > I'm not quite sure what you mean by "allowed host APIs", but there are > lots of synchronous APIs in Workers: File API, Filesystem API, IndexedDB. > These are all new APIs, not historical accidents (like sync XHR in the UI > thread). Synchronous (blocking) APIs in workers is entirely by design, in > order to allow writing clean, linear code instead of code that has to yield > to the calling environment all the time. > Sorry, I should've been clearer - I was referring to the renderer-to-worker messaging API - all event based, all async. TBH, at this point I'd be more interested in an actual prototype implementation to see the effects it would have on Worker to Worker messaging, SharedWorker etc. Rick > -- > Glenn Maynard > >
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 6:17 PM, Rick Waldron wrote: > No, it's not. Messaging should not block either process. > No, it's perfectly fine to block a worker, as long as the worker explicitly requests it and is expecting it. I don't know what that means. Synchronous APIs are one of the major > reasons to have Workers in the first place. > > Considering the current messaging API and the allowed host APIs, I > strongly disagree. > I'm not quite sure what you mean by "allowed host APIs", but there are lots of synchronous APIs in Workers: File API, Filesystem API, IndexedDB. These are all new APIs, not historical accidents (like sync XHR in the UI thread). Synchronous (blocking) APIs in workers is entirely by design, in order to allow writing clean, linear code instead of code that has to yield to the calling environment all the time. -- Glenn Maynard
Re: Synchronous postMessage for Workers?
On Nov 17, 2011, at 2:37 PM, Glenn Maynard wrote: > On Thu, Nov 17, 2011 at 2:16 PM, Rick Waldron wrote: > This is counter to the whole premise of Workers, which should be independent > of their renderer process and certainly not block themselves while waiting > for responses from the renderer (which inherently describes an async > behaviour). > > That's backwards. The premise is that the renderer (UI) will not be blocked > by workers, not that workers won't be blocked by the renderer. No, it's not. Messaging should not block either process. > > > Sync apis are sore thumb in GlobalWorkerScope's world. > > I don't know what that means. Synchronous APIs are one of the major reasons > to have Workers in the first place. Considering the current messaging API and the allowed host APIs, I strongly disagree. > > -- > Glenn Maynard >
Re: Synchronous postMessage for Workers?
It seems like this mechanism would deadlock a worker if two workers send each other a synchronous message. dave On Thu, Nov 17, 2011 at 10:37 AM, Joshua Bell wrote: > Jonas and I were having an offline discussing regarding the synchronous > Indexed Database API and noting how clean and straightforward it will allow > Worker scripts to be. One general Worker issue we noted - independent of > IDB - was that there are cases where Worker scripts may need to fetch data > from the Window. This can be done today using bidirectional postMessage, > but of course this requires the Worker to then be coded in now common > asynchronous JavaScript fashion, with either a tangled mess of callbacks or > some sort of Promises/Futures library, which removes some of the benefits > of introducing sync APIs to Workers in the first place. > > Wouldn't it be lovely if the Worker script could simply make a synchronous > call to fetch data from the Window? > > GTNW.prototype.end = function () { > var result = self.sendMessage({action: "prompt_user", prompt: "How > about a nice game of chess?"}); > if (result) { chess_game.begin(); } > } > > The requirement would be that the Window side is asynchronous (of course). > Continuing the silly example above, the Window script responds to the > message by fetching some new HTML UI via async XHR, adding it to the DOM, > and only after user input and validation events is a response sent back to > the Worker, which proceeds merrily on its way. > > I don't have a specific API suggestion in mind. On the Worker side it > should take the form of a single blocking call taking the data to be passed > and possibly a timeout, and allowing a return value (on > timeout return undefined or throw?). On the Window side it could be a new > event on Worker which delivers a "Promise" type object which the Window > script can later fulfill (or break). Behavior on multiple event listeners > would need to be defined (all get the same "Promise", first "fulfill" wins, > others throw?). > >
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 3:47 PM, Joshua Bell wrote: > ^^^ Nit: That would revert back to being postMessage(), no new API on the > Worker side. > Right, I just copied your example. (You mean "no new API for sending messages"--the "get the next event" method would be new API for workers.) One concern with this overall approach is that any pending message would be > grabbed, not just one intended as a response. > You just create separate MessagePorts to segregate different types of messages. messagePort.getMessageIfExists would only retrieve messages on messagePort. "Retrieve the first message from a list of message ports", akin to poll/select, may also be useful, eg. getFirstMessage([port1, port2], timeout). I'm not sure if there are use cases for this, but it's worth mentioning. I agree that "return" makes more sense than "dispatch", since we're > introducing this to support a linear programming style. On the other hand, > you could emulate "return" with "dispatch" via helper functions that swap > in a temporary onmessage handler (a variant on your > getPendingMessageWithoutDelivery example in the older thread) > Right, you can emulate either using the other. Alternatively, do both: fire the event synchronously, then return it. -- Glenn Maynard
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 11:28 AM, Glenn Maynard wrote: > > We discussed a very similar thing about a year ago; I've been meaning to > bring that up again, so this is probably as good a time as any. > http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1075.html > Ah, thanks - I should have gone digging. > The proposal is to allow polling a MessagePort, causing the first queued > message, if any, to be dispatched (or alternatively, to be returned). This > could be easily extended to handle the above, by adding a "blocking > duration" parameter. > > For example, working from Jonas's getMessageIfExists proposal: > > > self.sendMessage({action: "prompt_user", prompt: "How about a nice game > of chess?"}); > ^^^ Nit: That would revert back to being postMessage(), no new API on the Worker side. > var msg = messagePort.getMessageIfExists(5.0); > if(msg && msg.data) { chess_game.begin(); } > > Here, 5.0 means to block for five seconds (with a sentinel like -1 would > mean "block forever"), and the return value is the MessageEvent, returning > null if no message is received. > One concern with this overall approach is that any pending message would be grabbed, not just one intended as a response. But we're talking about workers that are intending to run long-lived functions here anyway so they must explicitly block/poll to receive any communication. It's a more complicated model for developers, but the complexity is opt-in. So I like it. I preferred the "dispatch the first message" approach before, but your > blocking use case may make the "return the first message" approach better. > I agree that "return" makes more sense than "dispatch", since we're introducing this to support a linear programming style. On the other hand, you could emulate "return" with "dispatch" via helper functions that swap in a temporary onmessage handler (a variant on your getPendingMessageWithoutDelivery example in the older thread)
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 2:16 PM, Rick Waldron wrote: > This is counter to the whole premise of Workers, which should be > independent of their renderer process and certainly not block themselves > while waiting for responses from the renderer (which inherently describes > an async behaviour). > That's backwards. The premise is that the renderer (UI) will not be blocked by workers, not that workers won't be blocked by the renderer. > Sync apis are sore thumb in GlobalWorkerScope's world. I don't know what that means. Synchronous APIs are one of the major reasons to have Workers in the first place. -- Glenn Maynard
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 1:37 PM, Joshua Bell wrote: > Jonas and I were having an offline discussing regarding the synchronous > Indexed Database API and noting how clean and straightforward it will allow > Worker scripts to be. One general Worker issue we noted - independent of > IDB - was that there are cases where Worker scripts may need to fetch data > from the Window. This can be done today using bidirectional postMessage, > but of course this requires the Worker to then be coded in now common > asynchronous JavaScript fashion, with either a tangled mess of callbacks or > some sort of Promises/Futures library, which removes some of the benefits > of introducing sync APIs to Workers in the first place. > > Wouldn't it be lovely if the Worker script could simply make a synchronous > call to fetch data from the Window? > > GTNW.prototype.end = function () { > var result = self.sendMessage({action: "prompt_user", prompt: "How > about a nice game of chess?"}); > if (result) { chess_game.begin(); } > } > We discussed a very similar thing about a year ago; I've been meaning to bring that up again, so this is probably as good a time as any. http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1075.html The proposal is to allow polling a MessagePort, causing the first queued message, if any, to be dispatched (or alternatively, to be returned). This could be easily extended to handle the above, by adding a "blocking duration" parameter. For example, working from Jonas's getMessageIfExists proposal: self.sendMessage({action: "prompt_user", prompt: "How about a nice game of chess?"}); var msg = messagePort.getMessageIfExists(5.0); if(msg && msg.data) { chess_game.begin(); } Here, 5.0 means to block for five seconds (with a sentinel like -1 would mean "block forever"), and the return value is the MessageEvent, returning null if no message is received. I preferred the "dispatch the first message" approach before, but your blocking use case may make the "return the first message" approach better. I think this is a fundamental missing piece to worker communication. A basic reason for having Workers in the first place is so you can write linear code, instead of having to structure code to be able to return regularly (often awkward and inconvenient), but currently in order to receive messages in workers you still have to do that. The use case that lead me to this initially was wanting to cancel operations cleanly, without having to terminate and reinitialize the worker entirely, eg. for input completion where processing restarts on each keypress. (That was an issue because the completion was initialized from localStorage, making startup expensive; IndexedDB will help that particular example, but this applies to any worker with nontrivial startup times.) -- Glenn Maynard
Re: Synchronous postMessage for Workers?
On Thu, Nov 17, 2011 at 1:37 PM, Joshua Bell wrote: > Jonas and I were having an offline discussing regarding the synchronous > Indexed Database API and noting how clean and straightforward it will allow > Worker scripts to be. One general Worker issue we noted - independent of > IDB - was that there are cases where Worker scripts may need to fetch data > from the Window. This can be done today using bidirectional postMessage, > but of course this requires the Worker to then be coded in now common > asynchronous JavaScript fashion, with either a tangled mess of callbacks or > some sort of Promises/Futures library, which removes some of the benefits > of introducing sync APIs to Workers in the first place. Workers are suited quite well to Promises/Futures apis. Sync apis are sore thumb in GlobalWorkerScope's world. > > Wouldn't it be lovely if the Worker script could simply make a synchronous > call to fetch data from the Window? > > GTNW.prototype.end = function () { > var result = self.sendMessage({action: "prompt_user", prompt: "How > about a nice game of chess?"}); > if (result) { chess_game.begin(); } > } > > The requirement would be that the Window side is asynchronous (of course). > Continuing the silly example above, the Window script responds to the > message by fetching some new HTML UI via async XHR, adding it to the DOM, > and only after user input and validation events is a response sent back to > the Worker, which proceeds merrily on its way. > > I don't have a specific API suggestion in mind. On the Worker side it > should take the form of a single blocking call taking the data to be passed > and possibly a timeout, and allowing a return value (on > timeout return undefined or throw?). > This is counter to the whole premise of Workers, which should be independent of their renderer process and certainly not block themselves while waiting for responses from the renderer (which inherently describes an async behaviour). > On the Window side it could be a new event on Worker which delivers a > "Promise" type object which the Window script can later fulfill (or break). > Behavior on multiple event listeners would need to be defined (all get the > same "Promise", first "fulfill" wins, others throw?). > > Rick
Synchronous postMessage for Workers?
Jonas and I were having an offline discussing regarding the synchronous Indexed Database API and noting how clean and straightforward it will allow Worker scripts to be. One general Worker issue we noted - independent of IDB - was that there are cases where Worker scripts may need to fetch data from the Window. This can be done today using bidirectional postMessage, but of course this requires the Worker to then be coded in now common asynchronous JavaScript fashion, with either a tangled mess of callbacks or some sort of Promises/Futures library, which removes some of the benefits of introducing sync APIs to Workers in the first place. Wouldn't it be lovely if the Worker script could simply make a synchronous call to fetch data from the Window? GTNW.prototype.end = function () { var result = self.sendMessage({action: "prompt_user", prompt: "How about a nice game of chess?"}); if (result) { chess_game.begin(); } } The requirement would be that the Window side is asynchronous (of course). Continuing the silly example above, the Window script responds to the message by fetching some new HTML UI via async XHR, adding it to the DOM, and only after user input and validation events is a response sent back to the Worker, which proceeds merrily on its way. I don't have a specific API suggestion in mind. On the Worker side it should take the form of a single blocking call taking the data to be passed and possibly a timeout, and allowing a return value (on timeout return undefined or throw?). On the Window side it could be a new event on Worker which delivers a "Promise" type object which the Window script can later fulfill (or break). Behavior on multiple event listeners would need to be defined (all get the same "Promise", first "fulfill" wins, others throw?).