OCaml multicore, effects and js_of_ocaml

With multicore landing soon, and algebraic effects coming as the next step the question arises - how is this going to work with js_of_ocaml backend? Gopherjs (Golang to JavaScript transpiler) boasts support of Goroutines and it really works in practice. Are there any plans to introduce similar transformations for green threads in OCaml with effects?

6 Likes

@avsm is there some game plan for JS compilation in OCaml 5+? js_of_ocaml multicore support issue references some relevant work by OCaml multicore project participants, but it’s unclear if that work succeeded or where it can be tracked. JS target is important for significant part of OCaml community and I thing some visibility on what’s happening or what’s going to happen with this would be much appreciated.

1 Like

I’m not aware of any formalised game plan. Originally to get effects in jsoo there was the approach @Armael implemented using CPS which I then tried to port to js_of_ocaml.3.9.0 and 4.12+domains+effects (see here). The major downside is that the CPS code is slow (and adds some time to jsoo compilation). I remember reading/being told that this can be improved by doing a selective CPS. Just to clear this wasn’t a planned bit of work, more just me experimenting in my own time :))

EDIT: I’ll add this to that tracking issue

1 Like

I wonder how critical it is to get multicore working for JSOO, given that JS runtime itself is single-threaded? Doesn’t Lwt’s concurrency model make much more sense for targeting JS? Also considering the fact that JS platform’s ‘native’ concurrency model is JS Promise, so shipping custom concurrency or multicore runtimes on top of that will only add layers of abstraction with no real benefit…

2 Likes

Effects are designated as the unifying force of Lwt/Async dichotomy (if I get it right), and if effects are not going to be supported on JSOO, a bunch of libraries will stay on Lwt because that still works there, continuing the ecosystem split.

Multicore itself seems orthogonal to effects, but imagine a library that wants to be thread safe and uses a bunch of mutexes internally. Nothing actually stops it from working on JSOO if JS runtime supports mutexes (actually this is what Gopherjs is doing - it runs multithreaded code in single threaded scheduler, and libraries designed for multiple threads can work on JS without extra effort in most cases).

1 Like

From what I understood, having effects would not really change anything w.r.t. Lwt/Async, they might just be ported over to work using effects going forward, but there would be no real change to their APIs.

Maybe I’m misunderstanding?

imagine a library that wants to be thread safe and uses a bunch of mutexes internally.

OCaml and Lwt both ship with a Mutex module (Mutex, Lwt_mutex). Do these not work on JSOO?

As I understand it, any code that uses effects at all won’t be compatible with jsoo, regardless of if it exposes or consumes those effects through a monad like LWT or Async.

Right now I think that even the multicore stdlib isn’t compatible.

2 Likes

There’s no really clean answer for jsoo compilation, with the best mechanism currently being a CPS translation which can “thread” the effect handling through the control flow of the program. As @patricoferris observes and has kindly forward ported, there is a prototype version of this that @Armael built while interning at OCaml Labs a few years ago. If someone wants to have a go at building a selective CPS version of this that is more efficient, then that’d be great.

Ultimately, our great hope is that wasm will take over from JavaScript as the compilation target of choice, and the effect handling story is much more rosy there. @kayceesrk has recently been active in the WebAssembly stacks working group, and there is an extension proposal in wasm that has the right primitives for efficient compilation of effect-handler-using OCaml to that.

Will wasm adopt the stack switching extension before OCaml 5.0 is out and we have a significant body of code using effect handlers? Only time will tell, as indeed will the number of motivated hackers who can work on either the jsoo or wasm compilation side to help advance the state-of-the-art here.

7 Likes

It would be useful to state the obvious first. If you don’t care about parallel domains and effect handlers, it should be fairly straight-forward to support jsoo complication for OCaml 5.0.

For effect handlers, CPS is one way to compile them. But there are also other strategies that @dhil, Sam Lindley, Bob Atkey, Jeremy Yallop and I explored a few years ago: https://www.dhil.net/research/papers/handlers_js-proweb2018.pdf. The gopherjs strategy for compiling go routines looks like trampolining, which is one of the strategies that we’d explored. Most of these compilation strategies tend to affect the performance of code that doesn’t use effect handlers since the transformations required to support suspending and resuming computations are program-wide. That said, it would be useful to replicate the experiments for OCaml 5.0 on jsoo as our experiments were not on jsoo (which can optimise whole programs) and JS engines get better all the time.

Wasm effect handlers make it almost trivial to compile OCaml effect handlers to them, but that is not something that can replace targeting JS in the short term. For one, there is no OCaml to Wasm compiler yet. :expressionless:

6 Likes

Right but unless I miss something it will break the current js_of_ocaml model which basically takes any OCaml bytecode to the browser (modulo C primitives/libraries).

This is a very good user experience as library authors do not need to care about JavaScript compilation. If you need to start tracking which libraries do use effects and does who don’t and live in the fear a library author might start to use them in the next version this is no longer nice :–)

Another thing is that according to what was answered to me here, accessing what you are actually interested in accessing when you compile for the browser – that is the browser APIs – doesn’t seem obvious/streamlined yet. I gather WASM is new and thus cool and all that, but without a good FFI to the browsers API it’s just a useless gimmick to me.

6 Likes

Fragmenting the already small OCaml ecosystem even further with the warning “don’t use effects for anything if any transitive user might want to use it in a web browser” feels like a last ditch resort. If we are forced down this road, we should make sure that the stdlib never uses effects, and that “uses effects” is tracked at the library level (via dune?) and enforced at build time so that people don’t accidentally pick up dependencies that use effects.

1 Like

There are already things in the ocaml library that you can’t use when compiling to javascript, including most relevantly the Thread module (at present non-parallel). When I last looked at it, also not available were most of the Sys module and all of Unix except time functions. I doubt adding effect handlers is going to surprise many people.

5 Likes

At Jane Street at least, the Unix and Sys modules are banned in libraries that claim to be jsoo compatible, and this is enforced at compile time (by shadowing those modules with empty modules).

I don’t think that Dune has this yet, but I think it would be valuable.

Edit: ok, not all of sys; lots of those functions are platform independent

1 Like

I don’t know what the Jane Street libraries do, but from my experience JSOO appears to give you a compile error if you call up functions in Sys or Unix which it has not wrapped, and ditto the Thread module. I imagine JSOO could do the same with respect to effects without great difficulty. I doubt that dune has to do anything.

I imagine that what would make support for effects desirable in JSOO is a situation where Lwt moves from a monadic implementation to effects. At some point I suspect that will happen.

That’s not the point.

Sniffing uses of system/C libraries is easy to do. Sniffing uses of effects, a language construct which could well be used only internally by a library is an entirely different thing.

3 Likes

As JSOO converts from ocaml bytecode to javascript, wouldn’t there be something in the bytecode to alert JSOO that there is something it can’t deal with (in this case, the use of effects), and error out? If you say no I believe you: I don’t know enough about ocaml’s bytecode to form a view.

Of course it will (and it likely already does).

But again that’s not the point. The point is that currently, the powerful promise of js_of_ocaml is: if you have pure OCaml code we guarantee you can compile it to JavaScript. If effects are not supported that’s no longer the case and makes js_of_ocaml a much less reliable tool.

3 Likes

Agreed. Throwing an exception when an unsupported API is called is one thing, but missing entire language features is another.

I am afraid I have lost the ability to understand the point. You seemed to suggest first that there as a difficult in “sniffing” uses of effects, which would be a problem for JSOO. You now seem to suggest above that there isn’t.

For what it is worth, I was referring to the fact that not all ocaml code can be compiled to Javascript at the moment anyway. Possibly by “pure” you mean “not including ocaml library modules wrapping system specific (that is, POSIX specific) functionality”. If so then I was suggesting that one could add “effects” to the list without surprising a user.

I understand that effects are a language construct and not something implemented in a module in the ocaml library. I also understand the desirability of supporting effects in JSOO. If that is all there is to be said then I am not sure there is anything left of substance so let’s leave it here.

Sorry, I defer to @TyOverby which said it in a much more concise and eloquent way than I did :–)

Not in a programming language that supports abstraction.

2 Likes