News for hackers. Stuff that matters.

flagxor

Re:Concurrent JavaScript: It can work on Thursday August 31, 2017 @06:21PM (#15144465)
setTimeout is obviously a simpler primitive to understand in isolation than monitors/conditionvars, but I would argue that when used in equally complex scenarios, similar challenges emerge.

Something like Dinning Philosophers is no less tricky to express + understand with an event loop, and with JS's async await probably would most cleanly be expressed in a style that mirrors a monitors/conditionvars version.

The fact that JS has added async await suggests demand for the convenience of concurrent blocking threads. While async-await manages to separate out non-async code to a degree, once an await happens, the global state can also be arbitrarily mutated no differently than with threads.

  function block() { return new Promise(function(a,b) { setTimeout(a, 0); }); }
  var x = 0;
  (async function foo() {
     x = 1;
     await block();
     console.log(x);
  })().then();
  (async function bar() {
     x = 2;
  })().then();
Concurrency is hard, but event loops aren't a magic wand.
Re:Concurrent JavaScript: It can work on Thursday August 31, 2017 @03:02PM (#15142852)
Many factors and capabilities went into Firefox's success. While it's easy to enumerate the primitives required in hindsight, I'm doubtful that if OSes of the period had taken a restrictive stance based on contemporary ideas of what should be allowed, that an easy time would have been had.

This is not hypothetical, consider the present. While Firefox on iOS exists, it's just a branding skin over WebKit, due to a similar flavor of security paternalism around JITing code (only bad people write self modifying code :-). If Firefox had needed to differentiate itself originally in such a market, it's doubtful it would have had much success.

A threading free-for-all may be the wrong abstraction to use for many applications, but it has the virtue of being a decent stand-in for the hardware's actual capabilities. It's also close enough to ground truth that most other abstractions can be built on top of it. Imagine how unpleasant building a browser on top of Workers + ArrayBuffer transfer would be (especially given the lousy multi-millisecond latency of postMessage in most browsers). Also, consider that while there is often loud agreement that raw threads are dangerous, after decades of research, there's little consensus on the "right" option amongst many alternatives.

SharedArrayBuffer is nearly as powerful as the proposal, but not quite. For example, while it allows writing a multi-threaded tree processing library, it would have trouble exposing an idiomatic JS API if the trees in the library live in a single SAB (as JS has no finalizers etc. to enable release of sub-allocations of the SAB). The options are either one SAB per tree (which likely performs badly), an API where JS users need to explicitly release trees when done with them, or leaking memory. With the proposal, each tree node could be represented directly as a JS object. The proposal may not be the best way to fix this problem, but we definitely still have gaps in JS concurrency.

Agreed this would be a serious undertaking, however, and not to be lightly considered.

The proposal goes a long way to make the case this can be implemented performantly, but some deep thought should go into how it would alter / constraint future optimizations in JS JITs.

Re:Concurrent JavaScript: It can work on Wednesday August 30, 2017 @11:22PM (#15137943)
This seems rather racy in Chrome, despite the I/O being deferred to the end :-)

  (function() {
    var x = '';
    setTimeout(function() { setTimeout(function() { x += 'a'; }, 6); }, 4);
    setTimeout(function() { setTimeout(function() { x += 'b'; }, 5); }, 5);
    setTimeout(function() { console.log(x); }, 50);
  })();
It's a fair point that generally I/O is the source of the bulk of the non-determinism in most JS programs. But if that I/O non-determinism is present (as it is in most useful programs), event loops aren't a panacea to avoid peril from it.

Concurrency introduces another source of non-determinism. But just as good programs use care with the ideally limited amount of code responding to events, good concurrent programs use similar care with access to shared state.

I'm unsure if the strawman syntax proposed encourages that care, but it is interesting that it can at least be done without breaking basic safety + performance. With SharedArrayBuffer on the way, we'll get all the non-determinism of parallel execution peeping through to JS without a particularly JS friendly syntax, so it's at least worth thinking about if something should be added to JS.

Re:Concurrent JavaScript: It can work on Wednesday August 30, 2017 @10:07PM (#15137635)
> Are you sure that setTimeouts are run in a non-deterministic order?

Certainly, if they are issued from different callbacks. :-) And in relation to how they may happen to be interleaved with I/O.

Also add to the non-determinism bucket: the order in which messages arrive from separate Workers.

> Callbacks can only come back in an unexpected order if you are using I/O.

Which abounds and takes many forms both in the browser and node.js.

> A broken callback chain is not the traditional definition of "deadlock".

Indeed, but it is the same class of developer hazard at play: waiting for an event to happen than will never come. Admittedly, only a subset of dropped callback chains correspond to the strict definition of deadlock: those where a chain is involved in marking a state/resource as available.

For example: I ignore the next button press on a ui that disables the button pending a reply because I accidentally failed to update the button state when a network request failed.

Re:Concurrent JavaScript: It can work on Wednesday August 30, 2017 @07:53PM (#15137103)
Event loops have these too, they just go by different names:

* non-determinism -> order in which setTimeouts run

* race conditions -> callbacks happen in an unexpected order

* deadlock -> broken callback chain

Re:Concurrent JavaScript: It can work on Wednesday August 30, 2017 @07:44PM (#15137045)
As long as we offer a similar `unsafe` option, a stronger type system around mutability+concurrency might have a range of benefits for JS. Rust's definitely has a number of virtues.

A little hard to imagine grafting onto JS though. :-)

Re:Concurrent JavaScript: It can work on Wednesday August 30, 2017 @06:26PM (#15136639)
It would have been a shame if the OSes on which Firefox runs had similarly limited access to shared memory to one particular "safe" style in the spirit of paternalistic caution.

Would Rust/Servo have been possible without access to the raw rope?