4 ms·
In my mind this is a multifaceted issue. One major factor is the special semantics of execution in Erlang VM compared to most other languages. Of note are: *
by hansihe 7y ago
In my mind this is a multifaceted issue.
One major factor is the special semantics of execution in Erlang VM compared to most other languages. Of note are:
* Guaranteed tail calls. There is no other way of doing a loop in Erlang other than recursing, so this point is really important. Although I can certainly imagine making this work with a JS target, we would have to perform certain code transformations that would most likely make the JS JIT a lot less effective.
* Preemption of Processes. Processes are the name of the lightweight actors used in the Erlang execution model. Each process is only allowed to run for a certain timeslice before execution has to be preempted. Although, again, I could imagine implementing this in a similar way as I would implement guaranteed tail calls, this would fully break up the control flow of a function, further disadvantaging the JS JIT.
* The semantics of the language term system. While this is probably one of the smallest issues for a JS target, it would still require us to implement and frequently call into relatively complex term operations that are implemented on top of the JS object model. I can't imagine this interacting well with the above two points in terms of performance.
* Concurrency/message passing model. One of our goals is exploring writing more fully featured applications in Erlang and then running it in the browser. As such, having the same concurrency model as the BEAM is critical. Using webworkers and utilizing shared memory through SharedMemoryBuffer (reenabled in chrome, let's hope firefox gets somewhere with this soon too), we believe makes it possible to implement things in a way that behaves very similar to the BEAM.
We want to invest heavily in the compiler in order to generate the best possible WASM code, which, given we play our cards right in codegen, should be further optimizable by the WASM engine. This involves inferring types and generating specialized code. Since most of Erlangs BIFs (built in functions) accept a much narrower array of types than what a lot of other dynamic languages do, we can draw relatively good type information from that.
This above is all an answer specific to the WASM/JS question, but doesn't even touch on the further goals of the project. While WASM is our primary focus at the moment, we also support native targets.
As for compilation to JS, ElixirScript (https://github.com/elixirscript/elixirscript https://github.com/elixirscript/elixirscript) is prior art here. I am not involved in this project, so I can't really answer to what design decisions they made, but it is interesting to compare with regardless.
Again, time will obviously tell how well all of this will work out, but from what we have seen thus far, our approach is fairly solid.
- pron 7y agoWith the possible exception of tail calls (which would require a bit of work), I don't see how any of those issues won't be better served by JS than by WASM, even if you did work against the JIT, and for less effort and with more features. It's just really hard to beat decent JITs with AOT compilation for an untyped language -- and V8's JIT is more than just decent -- even when the JIT is having a bad day, not without some very powerful whole-program analysis, and that costs a lot of time and money. But V8 is especially well optimized for a "broken", or "preempted" control flow, as that's just how JS is written, with or without async/await. Native targets are another matter, of course. Anyway, it would be interesting to see results. Beating BEAM's performance is not hard. Thank you for your answer.
- mwcampbell 7y ago> Beating BEAM's performance is not hard. Interesting observation. The hype I've heard around Elixir and Phoenix makes it sound like BEAM's performance is amazing. But maybe that's only in comparison to Ruby (specifically the C Ruby interpreter).