Re: Sync API for workers

On 09/01/2012 11:19 PM, Rick Waldron wrote:
>
> David,
>
> Thanks for preparing this summary—I just wanted to note that I still stand behind my original, reality based arguments.
>
> One comment inline..
>
> On Saturday, September 1, 2012 at 12:49 PM, David Bruant wrote:
>
>> Hi,
>>
>> A Sync API for workers is being implemented in Firefox [1].
>> I'd like to come back to the discussions mentionned in comment 4 of the bug.
> The original post actually describes an async API—putting the word "sync" in the middle of a method or event name doesn't make it "sync".
>
> As the proposed API developed, it still retains the "event handler"-esque design (https://bugzilla.mozilla.org/show_bug.cgi?id=783190#c12). All of the
> terminology being used is "async":
> - event
> - callback
> - "onfoo"
>
> Even Olli's proposal example is async. https://bugzilla.mozilla.org/show_bug.cgi?id=783190#c9 (setTimeout)
>
> If the argument is "callback hell", save it—because if that's the problem with your program, then your doing it wrong (see: node.js ecosystem).
>
>
> If this API introduces any renderer process blocking, the result will be catastrophic in the hands of inexperienced web developers.


I haven't seen any proposal which would block rendering/main/dom thread


We've been thinking the following approaches:

Proposal 1
Parent Thread:
var w = new Worker('foo.js');
w.onsyncmessage = function(event) {
   event.reply('bar');
}
Worker:
var r = postSyncMessage('foobar', null, 1000 /* timeout */);
if (r == 'bar') ..
PRO:
- It's already implemented :)
CON:
- Multiple event listeners - Multiple reply() calls. How to deal with it?
- Multiple event listeners - is this your message?
- Wrong order of the messages in worker if parent sends async message just before receiving sync message
- The message must be read in order to reply


Proposal 1.1
Parent Thread:
var w = new Worker('foo.js');
w.onsyncmessage = function(event) {
   var r = new Reply(event);
   r.reply("bar");  // Can be called after event dispatch.
}
Worker:
var replies = postSyncMessage('foobar', null, 1000 /* timeout */);
for (var r in replies) {
   handleEachReply(r);
}
PRO:
- Can handle multiple replies.
- No awkward limitations on main thread because of reply handling
CON:
- A bit ugly.
- Reply on the worker thread becomes an array - unintuitive
- Wrong order of the messages in worker if parent sends async message just before receiving sync message
- The Reply object must be created during event dispatch.


Proposal 2
Parent Thread:
var w = new Worker('foo.js');
w.setSyncHandler('typeFoobar', function(message) {
   return 'bar';
});
Worker:
var r = postSyncMessage('typeFoobar', 'foobar', null, 1000 /* timeout */);
if (r == 'bar') ..
PRO:
- no multple replyies are possible
- types for sync messages
CON:
- Just a "single listener"
- It's not based on event - it's something different compare with any other worker/parent communication.
- Wrong order of the messages in worker if parent sends async message just before receiving sync message


Proposal 3
Worker:
postMessage("I want reply to this");
var events = [];
while (var m = waitForMessage()) {
   if (m.data != /* the reply * /) {
     events.push(m);
   } else {
     // do something with message
   }
}
while (events.length()) {
    dispatchEvent(events.shift());
}
PRO:
- Flexible
- the order of the events is changed by the developer
- since there isn't any special sync messaging, multiple event listeners don't
   cause problems.
CON:
- complex for web developers(?)
- The message must be read in order to reply
- Means that you can't use libraries that use sync messages. Only frameworks are possible as all message handling needs to be aware of the new 
syncmessages.




Atm, I personally prefer the proposal 3.


-Olli


>
>
> Rick
>>
>> A summary of points I find important and my comments, questions and concerns
>>
>> # Discussion 1
>> ## Glenn Maynard [2] Use case exposed:
>> Ability to cancel long-running synchronous worker task
>> "Terminating the whole worker thread is the blunt way to do it; that's
>> no good since it requires starting a new thread for every keystroke, and
>> there may be significant startup costs (eg. loading search data)."
>> => It's a legitimate use case that has no good solution today other than
>> cutting the task in smaller tasks between which a cancellation message
>> can be interleaved.
>>
>>
>> ## Tab Atkins [3]
>> "If we were to fix this, it needs to be done at the language level,
>> because there are language-level issues to be solved that can't be
>> hacked around by a specialized solution."
>> => I agree a lot with that point. This is a discussion that should be
>> had on es-discuss since JavaScript is the underlying language.
>> ECMAScript per se doesn't define a concurrency model and it's not even
>> on the table for ES.next, but might be in ES.next.next (7?). See [concurr]
>>
>> ## Jonas Sicking [4]
>> Ideas of providing control (read-only) over pending messages in workers.
>> (not part of the current Sync API, but interesting nonetheless)
>>
>>
>>
>> # Discussion 2
>> ## Joshua Bell [5]
>> "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."
>> => What are these benefits? Is the cost of the Promises/Future library
>> so high it
>> Back to Tab's point of the previous discussion, this is a language
>> issue, not an API issue. It ought to be solved at the language level
>>
>>
>> ## Rick Waldron [6]
>> "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)."
>> => Indeed. Having a blocked worker makes that when you need other tasks
>> to happen in parallel, you need to spawn new workers which is a waste of
>> resources, very much like Apache which opens a new thread for each HTTP
>> connection while some thread are idling (I don't know if it's still the
>> case, but it used to)
>>
>>
>> ## Glenn Maynard [7]
>> "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."
>> => A basic reason for having workers is to move computation away from
>> window to a concurrent and parallel computation unit so that the UI is
>> not blocked by computation. End of story. Nothing to do with writing
>> linear code. If JavaScript as it is doesn't allow people to write code
>> as they wish, once again, it's a language issue. Either ask a change in
>> the language or create a language that looks the way you want and
>> compiles down to JavaScript.
>>
>>
>>
>> I wish to add that adding a sync API (even if the sync aspect is
>> asymetrical as proposed in [1]) breaks the event-loop run-to-completion
>> model of in-browser-JavaScript which is intended to be formalized at
>> [concurr]. This model is what prevents web pages from ever freezing from
>> a deadlock. The proposed API preserves this, but create the threat of
>> deadlocks for workers.
>>
>> Besides programmer convenience, few arguments have been advanced to
>> justify the breakage of the current concurrency model (I don't even
>> think the breakage has been mentionned at all!). And as said several
>> times, programmer convenience are more of a language issue than an API
>> issue for the specific things we're talking about.
>> Also, I don't think I have seen mentionned use cases of things that are
>> not possible without a Sync API. Everything presented is already
>> possible (sometimes at arguably high costs like Glenn Maynard's use case
>> in discussion [1]).
>>
>> David
>>
>> [1] https://bugzilla.mozilla.org/show_bug.cgi?id=783190
>> [2] http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1075.html
>> [3] http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1082.html
>> [4] http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1086.html
>> [5] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/0965.html
>> [6] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/0966.html
>> [7] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/0967.html
>> [concurr] http://wiki.ecmascript.org/doku.php?id=strawman:concurrency
>

Received on Saturday, 1 September 2012 20:29:09 UTC