Sync IO APIs in Shared Workers

Hi all,

There has been some amount of debate about the virtue of sync IO APIs
in workers. Or sync APIs in workers in general.

One of the arguments made against sync APIs in workers made in [1] is
that even for workers, it is often important to keep code responsive
in order to react to actions taken by the user.

I.e. while locking up a worker thread for an extended period of time
won't cause problems like stuttered scrolling or UI that doesn't
visually react when you click them, you can still end up with apps
that seem unresponsive since the main thread is waiting to get back an
answer from a worker thread that is busy.

I honestly don't know what the right answer is. On one hand I could
definitely see code which does sync IO in a worker in order to search
for local data as the user types in a textbox, for example to
implement autocomplete. In such an instance it's very easy to
accidentally create unresponsive UI since it's not possible to abort
the current search when the user types another key.

On the other hand, having a worker which uses sync IO to synchronize
local data with data from a server can produce significantly simpler
code than doing the same thing with async IO. And this worker might
never need to react to user actions and thus it's no problem to not
handle incoming messages with low latency.

I also don't buy the argument that we can make async programming so
convenient that there's little cost to async APIs compared to sync
APIs. As we add convenience methods like task.js to make async code
look like sync code, the more we're creating an environment where
multiple code paths are running in parallel in the same heap. I.e. the
more we make it look like C-style threading. Yes, the differences are
there and they are important. But as the differences between async and
sync code gets smaller, the hazards get more real.

One thing that we so far have not seemed to consider is fixing the
problems with sync code raised in [1] and elsewhere.

We could enable sync IO APIs in workers while still allowing the
worker thread to remain responsive to messages from the main thread.
One solution is the API in [2]. Using that API the main thread can
send a error-response to a sync request for IO before the IO has
finished.

Another solution would be to use real sync IO APIs, but expose an
object in the parent thread which allows the parent to abort the
current operation.

Something else that could improve responsiveness while still allowing
people to write synchronous code is the ability to check if there are
pending messages on a channel without having to return to the event
loop. That way the code can keep running until there's a message to
process, and only return to the event loop when there is.

I'm not sure if any of these ideas will work in practice. Or if they
helpful but insufficient to solve the problem. More research is
needed.

The problem of unresponsive workers is arguably worse for
SharedWorkers. For shared workers a long running request from one
window will block processing for all windows.

One possible action here would be to disallow sync APIs in shared
workers for now. This way we can use dedicated workers as a test bed
to see if sync APIs are a problem, and if they are, if that problem
can be fixed.

The only browser shipping SharedWorkers is Chrome (not sure if Opera
does too?), so if the Blink developers are willing to remove it from
there, then this would be doable. Firefox has an implementation of
SharedWorkers too, but it's not yet shipping. I think we'd be willing
to turn off sync APIs in them before shipping.

[1] http://infrequently.org/2013/05/the-case-against-synchronous-worker-apis-2/
[2] http://lists.w3.org/Archives/Public/public-webapps/2013OctDec/0142.html

/ Jonas

Received on Friday, 22 November 2013 02:34:54 UTC