
Concurrent JavaScript: It can work - stablemap
https://webkit.org/blog/7846/concurrent-javascript-it-can-work/
======
Animats
Of course the language can be made to support it. Given the way Javascript is
used, the question is whether supporting it will create a big mess.

They have some good ideas. One is that variables can be marked as restricted
to one thread. That should be the default. Other languages could benefit from
that feature. Python, for example. If you want to get rid of the Global
Interpreter Lock, knowing which variables can't be shared between threads is a
big help.

Variables should be owned by a thread or owned by a lock. Rust went that way,
and it works well. The proposal here is old C-style locking, where there are
locks and variables, but the language doesn't know which locks are protecting
which variables.

~~~
pizlonator
I think it would be weird if objects were thread-restricted by default.
Concurrency is most fun when it's easy for a thread to access an object it
wants.

~~~
richardwhiuk
You say fun, but what you mean is twisted mess.

~~~
pizlonator
WebKit uses threads. WebKit is not a twisted mess.

~~~
coldtea
WebKit needs tons of extra effort to keep it from being a twisted mess
precisely because it uses threads.

~~~
LeoNatan25
Any well written software requires effort to properly design and maintain.
What’s the argument here? “Don’t give them shotguns, they might shoot
themselves”?

~~~
PeCaN
Don't load the shotguns, turn off the safety, point it at their foot and tell
them “please be careful”.

------
zackmorris
I'm late to the party but please for anyone reading this, look into the actor
model. Shared mutable state quickly becomes unmaintainanble. It used to be
slow to do shared immutable state but that's no longer the case. Today there
are many better ways to do shared memory with copy-on-write so data is only
copied if it's changed. Think back on history - there are only a handful of
computation approaches that have stood the test of time. Pipes in unix,
spreadsheets, data management systems like MS Access or FileMaker. Had
concepts from those programs made it into programming, our lives would be a
lot simpler today. We don't need to torture ourselves for imagined efficiency
by copying the C threading model that quickly dissolves into spaghetti.

~~~
porker
> there are only a handful of computation approaches that have stood the test
> of time. Pipes in unix, spreadsheets, data management systems like MS Access
> or FileMaker. Had concepts from those programs made it into programming, our
> lives would be a lot simpler today.

Can you go into more detail on which concepts from Pipes in unix,
spreadsheets, data management systems like MS Access or FileMaker you're
thinking of? My familiarity with the tools is leading to blindness about
application...

~~~
zackmorris
Ya what I was trying to say for each of those is:

Pipes/streams: one way channels between isolated executables

Spreadsheets: the only form of functional programming that's reached mass
adoption (equivalent to lisp for the most part)

DBMS: the only form of declarative programming other than the web that's
reached mass adoption. In this case the view has two-way binding to the data,
but relationships are declarative and the controller has been abstracted into
the GUI and event callbacks on buttons etc (controller is the weakest portion
of MVC)

All of these concepts could/should make it into mainstream programming
languages. Try searching for Redux, Elm, software transactional memory, the
Clojure state store, coroutines (which are interchangeable with state machines
but without goto).

I believe that we can use all of these techniques without the ugly syntax of
functional programming languages like Haskell, Scala, R, etc. For example
Elixir is trying to be a kinder, gentler Erlang.

------
ender7
Please, no. Shared-by-default heap memory is one of the greatest mistakes ever
made in language design. We need a better design justification than it's the
easiest thing to implement right now.

~~~
imtringued
The justification is that when you have an array of 100000 elements and split
it into into isolated chunks that can be processed without any synchronisation
and then marshall it into json and then actually do the computation and then
marshall the result into a json string and marshall it back into a javascript
array is very wasteful. Heck even when I'm passing immutable messages I'd
still implement it via shared memory to avoid the wasteful marshalling step.

~~~
spankalee
Fork/join on arrays and trees would be an easier to manage model, IMO.

~~~
pizlonator
You can implement that on top of threads.

~~~
spankalee
Of course you can. You can implement anything on top of threads, especially
non-determinism, race conditions and deadlocks.

~~~
flagxor
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

~~~
a-kojeve
Yeah, but nobody relies on the execution order of disparate callbacks to
achieve their results in JS. You're going to get burned in like two seconds if
you try to do anything you listed. Lower level concurrency primitives in other
languages allow developers to build fragile solutions which work 99% of the
time until they deadlock and everything blows up. The concurrency model in JS
is very explicit about being "no guaruntees."

~~~
pizlonator
There are many reasons why complex software fails in the 1% case. Concurrency
is not the only reason. In my experience it is not the top reason. Our top
hard-to-repro or no-repro crashes in JavaScriptCore are from non determinism
introduced by the workload itself. Inside our engine we have many sources of
nondeterminism that manifests even with concurrency features disabled.

------
spankalee
It's awesome to see work on concurrency, but I'd really like to se a model
that didn't involve shared memory.

JavaScript on the web already has the concept of Transferrables. It'd be great
to explore how user-land code could create transferrable objects and graphs of
them so they could be sent between threads without threads sharing the same
heap.

~~~
amelius
Sorry, but we need shared memory for fast sharing of large immutable data
structures.

~~~
spankalee
Then add immutable objects to JS, which enable a host of other optimizations
and are useful in single-threaded contexts too.

Shared-memory multithreading is just very difficult to use correctly. Actor-
style concurrency hasn't really caught on (possibly because of the poor
performance of workers and postMessage), but there is probably a middle ground
that's easier for developers to get right.

~~~
phailhaus
JS already supports immutable objects, by using Object.freeze().

~~~
bzbarsky
That doesn't really make things immutable. Even ignoring the deep vs shallow
issue, consider what effect Object.freeze has on a JS Map (hint: none, really;
you can still add/remove things).

~~~
phailhaus
Right, that's where libraries like ImmutableJS come in.

------
iainmerrick
I feel like most of the comments here are ignoring the fact that this is a
_straw man_ proposal, as the blog post emphasises several times.

They aren't proposing to add threads to JS in exactly this manner. They're
pointing out that it would be _technically feasible_ , for WebKit at least,
and wouldn't add any unnecessary overhead. The specific proposal is just a
starting point for discussion.

------
preek
JS already has a proper concurrency model which is the event loop. What it
doesn't have is a model for parallelism. It's important to understand the
difference! It can be hard to grasp at first, because few people make the
proper distinction.

If you're new to the subject, don't take my word on it, but watch the talk
"Concurrency is not parallelism" by Rob Pike[0]. It's highly recommended.

Learning a language that makes a proper distinction will help - I got it
through Clojure, but there's certainly others like (obviously) Golang.

0\. [https://youtu.be/cN_DpYBzKso](https://youtu.be/cN_DpYBzKso)

~~~
pizlonator
Even loop is not concurrency.

Just because concurrency and parallelism are different does not meant that
concurrency and event loops are the same.

~~~
loftyal
How? Explain please.
[https://en.wikipedia.org/wiki/Concurrency_(computer_science)](https://en.wikipedia.org/wiki/Concurrency_\(computer_science\))

"order-independent components", which makes sense for the Event loop.

~~~
pizlonator
I draw the line at whether the interleaving granule is under the programmer’s
control or not.

For example, I can say that _when a task executes on an event loop, no other
tasks are executing concurrently to it because the event loop executes tasks
sequentially_.

~~~
loftyal
Ok you draw the line there, but definitions are supposed to be commonly
understood, that's how language works...

~~~
pizlonator
Yeah, I agree it would be better if people in the event loop community learned
to use the word “concurrency” correctly.

------
bzbarsky
What's not quite clear to me is whether "the cell never moves" is one of the
assumptions that actually goes into making this work or not. And if it is, how
that plays with a compacting or generational collector, where you do in fact
want the cell to move.

~~~
pizlonator
From the standpoint of the concurrency scheme I'm proposing, it's OK to move
the cell in the GC. Then it becomes a standard GC moving problem.

In JSC we don't move cells for other reasons, and the point of saying that
they don't move is that the object model itself does not require the cell to
ever move.

~~~
bzbarsky
Thank you for the explanation!

------
zengid
Genuine question: Aren't locks a quagmire in terms of lock management? Why
start there?

~~~
pizlonator
All of the alternatives are an even bigger quagmire.

------
first_amendment
JavaScript is already concurrent. It isn't parallel though.

Is there any real world application that currently cannot exist without this
feature? It seems like a solution looking for a problem.

I can see needing the ability for parallel JS for highly-parallel compute-
heavy applications but those already seem serviced by SharedArrayBuffer.

So... why?

------
rmrfrmrf
Forgive the ignorance, but why do we need threads when we already have the
event loop?

And, as a follow-up, why introduce a new concurrency model that's based on
Java instead of, say, creating a concurrent "event pool" where execution order
isn't guaranteed and callbacks are executed with maximum concurrency (edit: to
clarify, I mean maximum parallelism)?

~~~
STRML
Event loops are great for handling work that can be handed off occasionally to
worker threads (like how Node works with libuv), but are awful when doing
consistent CPU-bound work, such as with games, 2D/3D visualizations, finance,
and the like.

SharedArrayBuffer is a nice primitive that allows multiple Threads (or
WebWorkers) to work on data in parallel. The additional primitives they're
proposing offer quite a bit of flexibility. For one, I would really like an
easy `new Thread(fn).asyncJoin()` to create a Promise to do expensive CPU-
bound work. There are a few npm modules that do some version of this but it
can be slow.

As for the concurrency model, it should be possible to delegate tasks to a
pool in this one. Map an array of input data and functions to an array of
promises, then Promise.all() or Promise.race() on them.

~~~
pitaj
I think that kind of stuff it much more relevant in the land of WebAssembly.
It _certainly_ makes sense there, but in normal JS, I doubt the usefulness.

~~~
STRML
It depends. It could be very useful for React/React Native, for one.

------
BatFastard
One other thing to consider, the SharedArrayBuffer can only carry limited data
types, it's not a shared object. I used Flash's SharedArrayBuffer and found it
was very limited in what you could use it for.

------
LeoNatan25
This is very interesting. If this is indeed implemented, it will remove a
serious hurdle from the equation of RN. Still JS, but the ceiling will go up
considerably.

------
rkeene2
JavaScript should just copy the Tcl threading model.

------
throwaway613834
They mean parallelism, right? Concurrency is what JS is already known for.

~~~
zzzcpan
Yeah, JS definitely has concurrency. He's just twisting the term a bit into
his world of shared-memory multithreading to make his model sound superior to
other concurrency models.

------
markc
Or use ClojureScript with core.async - which implements a go-like concurrency
model. (Not saying that's fully or equivalent, or meant to denigrate this
interesting work.)

------
einrealist
Yeah, and lets have the gazillion scripts, loaded by your usual favourite news
site, spawn 10 threads each...

For browsers, this is a bad idea. The biggest advantage of the event loop
approach is that it is somewhat deterministic. With threads, that determinism
goes out of the window. Lock-management? No way I do that for Browsers. I will
quit working on client-side code if that is becoming a requirement!

Threads for the server-side? I don't care.

~~~
blockoperation
Whether it's a good addition to the language or not is debatable, but as a
browser feature, it sounds terrifying. Browsers have a huge attack surface as
it is (I mean, WebGL is a thing – exposing GPU drivers to random untrusted
code on the internet, what a brilliant idea...), and exposing threading will
only make it worse. Every single API would have to be carefully audited and
made thread-safe, and I'm sure that many 'fun' bugs would crop up as a result.

~~~
TheCoreh
Which is why the proposal specifically says that only a few DOM APIs would be
exposed to background threads (Like console.log())

