Sdk: Compile Dart to WASM

Created on 15 Apr 2018  路  66Comments  路  Source: dart-lang/sdk

It would be very cool to add support for the WebAssembly

area-web customer-dart-sass type-enhancement web-libraries

Most helpful comment

Dart Sass is also very interested in WebAssembly. Our biggest user base runs Dart Sass on Node.js, but we consistently hear from our users that the performance of the compiled JS output is not up to par. Our users are comparing the performance of our dart2js output to Node Sass, which is a wrapper around a C++ library. Dart Sass via dart2js is 2x slower than Node Sass in the very best cases, and almost 6x slower when compiling some real-world libraries.

On the other hand, the main reason anyone uses Dart Sass over Node Sass is that it's vastly easier to install a library that doesn't require native compilation. So users have a choice: they can have an easy installation experience or fast compilation, and whichever they choose also comes with a bunch of subtle incompatibilities. It's not a great experience.

WebAssembly would give us the best of both worlds. It would almost certainly represent a major performance boost over dart2js because we don't have to deal with the overhead of JavaScript, and it's just as portable (and thus easy to install) as plain JS. Even if it the WASM binary had to ship with a full garbage collector until WASM supported it, it would make a huge difference to me and my users.


As an aside, can we re-open this issue, since the proposal is still under consideration?

All 66 comments

Yes it would. This is something we are looking at. Thank you.

What, is the effort of webassembly and is there a timeline, for implementation?

There is no timeline and no work is happening on this at the moment.

@mraleph thanks for answer, but how can I know that already happening?

@listepo-alterpost I am not sure I understand the question. Nothing is happening on this at the moment.

Using this in flutter apps would be a great usecase.

@b-strauss using it in what way?

I guess like Blazor alternative(Hummingbird)

@mraleph

WebAssembly is a cross platform format. If the DartVM had support for it, we could use the same WASM files on mobile Flutter apps as on web Flutter apps (with Hummingbird via calls to the JS WASM API).

@b-strauss There is definitely no plans to support running WASM binaries on Dart VM. You can run native code on mobile platforms - which means you can run anything you want and you don't need to compile to WASM first.

@mraleph You're right of course. But seeing聽that the target platforms for flutter will grow in the future (Web, Windows, macOS, fuchsia), having a single binary would make targeting these definitely easier. But I'm aware the cost for that would be high. ;)

Any news on this?

No news.

In general if you are interested in WASM support I recommend including rationale (e.g. "I am interested in WASM because ..."). Knowing use cases that people consider would help us to prioritise things. Thanks.

I am interested in WASM because ..

  • I have an existing SPA web app that relies on substantive library that isn't really JavaScript specific, but needs to run client side.
  • I want to develop a mobile app with same experience using Flutter, and would have to re-write and maintain a duplicate of this library in Dart alongside the existing JavaScript implementation.
  • I would like to be able to re-write that library in a language that targets WASM, and then be able to import that library from both web platform and flutter.

TLDR: code sharing of packages between client-side web & flutter.

@Schonhoffer You can already do this in multiple ways:

  • First option: Dart actually compiles to JavaScript - so if you just rewrite your library in Dart you will be able to use it from both JavaScript and natively from Flutter. [and if you are rewriting it anyway - why not in Dart?]
  • Second option: Dart allows you to interoperate with native libraries from Flutter (and this will get even better with FFI that is currently under active development). So you write your program in some native language like C++ (or Rust), compile it natively and use it from Flutter. You can also compile it to WASM and use it on the Web.

As you can see neither of these options requires any sort of WASM support from Dart.

Dart Sass is also very interested in WebAssembly. Our biggest user base runs Dart Sass on Node.js, but we consistently hear from our users that the performance of the compiled JS output is not up to par. Our users are comparing the performance of our dart2js output to Node Sass, which is a wrapper around a C++ library. Dart Sass via dart2js is 2x slower than Node Sass in the very best cases, and almost 6x slower when compiling some real-world libraries.

On the other hand, the main reason anyone uses Dart Sass over Node Sass is that it's vastly easier to install a library that doesn't require native compilation. So users have a choice: they can have an easy installation experience or fast compilation, and whichever they choose also comes with a bunch of subtle incompatibilities. It's not a great experience.

WebAssembly would give us the best of both worlds. It would almost certainly represent a major performance boost over dart2js because we don't have to deal with the overhead of JavaScript, and it's just as portable (and thus easy to install) as plain JS. Even if it the WASM binary had to ship with a full garbage collector until WASM supported it, it would make a huge difference to me and my users.


As an aside, can we re-open this issue, since the proposal is still under consideration?

For all of you:
in the following link is a survey about flutter directly from the flutter developers. Because Flutter and Dart are closely linked together there are some questions about Dart and one particular about dart support for web assembly.
Could be interesting?!

https://google.qualtrics.com/jfe/form/SV_3W3aVD2y9CoAe6V?Source=IntelliJ&ClientID=cc844799-def7-4db0-8e50-d20606f2af1d

"Sorry, this survey is not active"

@mraleph The point is about easy interoperability. I can compile Rust/C/C++ to native, but having a to deal with this for every platform is cumbersome and unecessary on early versions of my app.

Do this makes any sense?

That and "it already compiles to JavaScript" is not really a big comfort because one of the main perks of using wasm instead of transpiling to JS is the incredible speed increase.

I am reopening the issue to indicate that this is something we are considering, even though we currently have no immediate plans to work on this.

@pie-flavor

one of the main perks of using wasm instead of transpiling to JS is the incredible speed increase.

WASM is not some pixie dust that makes your code magically faster. I actually have some serious doubts that compiling Dart to WASM would bring any speed increase, and in fact expect worse performance due to the lack of dynamic optimizations, insulation from underlying native architecture and inability to rely on builtin optimised primitives and standard library. The only performance characteristic that can potentially be improved by targeting WASM is startup latency. Additionally you will get somewhat predictable performance - but again, I actually doubt it would be better than peak performance you will get from good dart2js code.

I am reopening the issue to indicate that this is something we are considering, even though we currently have no immediate plans to work on this.

@mraleph Are you talking about running WASM binaries on Dart VM, or compiling Dart to WASM?

@b-strauss renamed issue to make it clear.

@mraleph Is running WASM on the Dart VM also something that is considered? Should there be a separate issue for that?

@b-strauss nothing has changed since my comment in January. There are no immediate plans for running WASM on Dart VM - because so far there was no strong demand or persuasive use case which would warrant adding such complexity to the VM.

Is running WASM on the Dart VM also something that is considered? Should there be a separate issue for that?

There are no immediate plans for running WASM on Dart VM - because so far there was no strong demand or persuasive use case which would warrant adding such complexity to the VM.

What about being able to reuse already-existing business logic coded in a wasm-compilable language?
Compiling to native in 2 or 3 platforms (iOS, Android, Web) is way harder then compile to WASM only and use it on the 3.

To be clear: Your team can have a stance against doing it or even doing it _right now_. But in no way there is "no use case" for running WASM along Dart code, in my opinion.

(cc: @mesquitaa)

Although my primary interest here is being able to compile Dart to WASM, I think @alanjds makes a really good point. I expect we're going to be seeing a lot more shared libraries targeting WASM in the next few years, and either Dart's support for that could be a feature that sets it apart from other language options, or its lack of support could be another drawback that makes JS more appealing.

@mraleph

WASM is not some pixie dust that makes your code magically faster.

Isn't it? That's pretty much the whole point of using a compiled instead of interpreted language. But that's just startup time; the real speedup is in not using a language where you can redefine anything anywhere at any moment, because that's the primary thing holding back the JIT. It's not necessarily that the WASM format is special; it's that its end format isn't JS.

@pie-flavor It is without doubt that WASM is a better compilation target than JS for languages like C/C++ and Rust - languages where you manage your memory manually, where your calls are most often statically dispatched and primitive types are unboxed.

However if you start moving away from this kind of languages towards languages like Dart - which are full of dynamic behaviour, boxed primitive types and GC you will discover it becomes harder to claim with absolute certainty that WASM is a better compilation target than JS - because you would be forced to compile various runtime components (e.g. method dispatch implementation) into WASM - while in JS you get those things from underlying JS runtime and they are implemented natively and heavily optimised.

Another interesting thing to consider is that dart2js essentially benefits from two compilation steps - AOT compilation to JS and dynamic optimisation of this JS later by JS JIT. If AOT compiler fails to statically specialise some call site, there is still a chance that JS VM would manage to do that. You don't get such luxury with WASM.

There are a lot of other factors to consider (e.g. builtin libraries - do you want to implement your own array like structure in WASM with associated performance penalty, or do you just want to use heavily optimised native array?), etc, etc.

That said - I don't doubt that there are workloads and programs that would benefit from Dart targeting WASM. All I am saying is that expecting all Dart programs to magically get faster is incorrect.

@pie-flavor here is very good Google I/O talkt about js and WAM. If you don't wanna watch the whole talk. Just jump to 17:38 https://youtu.be/njt-Qzw0mVY

WASM will speed up webgl-based applications.

In the Google i18n team, we are considering options to build a single shared library that targets multiple runtimes. We are evaluating WebAssembly as a compile target, such that our i18n library can be invoked from any VMs that support WASM. Support for WASM on the Dart VM would be a boon to the impact of our i18n-on-WebAssembly proposal.

Let's use #37355 for interop with WASM and keep this one for compilation to WASM.

Dart Sass is also very interested in WebAssembly. Our biggest user base runs Dart Sass on Node.js, but we consistently hear from our users that the performance of the compiled JS output is not up to par. Our users are comparing the performance of our dart2js output to Node Sass, which is a wrapper around a C++ library. Dart Sass via dart2js is 2x slower than Node Sass in the very best cases, and almost 6x slower when compiling some real-world libraries.

@nex3 - a useful data point here (if possible) would be Sass with Dart AOT. A hypothetical Dart-on-WASM should be slower than that. I.e., the answer here might be that we need to focus on general Dart AOT performance first.

We track Dart Sass benchmarks here, including running from a script snapshot, from a native executable, and from JS (our three deploy configurations). AOT performance is competitive with LibSass (written in C++) across the board so we're pretty happy with that. Node.js performance is out big pain point, ranging from about 2x slower than AOT at best to about 5x slower on one real-world benchmark. Even getting it to a consistent 2x slower would be a major improvement.

Thanks, @nex3 . Just to clarify, by "native executable", you mean via dart2aot and dartaotruntime?

That's right.

As I proposed on Flutter's Github [1]
if Flutter Web would use WASM instead of dart2js
it would feel "future proof"

(Hope to not have the thread locked :)

We track Dart Sass benchmarks here, including running from a script snapshot, from a native executable, and from JS (our three deploy configurations).

@nex3 how are you benchmarking these? where's the benchmark script?

@mindplay-dk IIRC pub run grinder benchmark runs benchmarking scripts. See https://github.com/sass/dart-sass/blob/master/tool/grind/benchmark.dart for the actual code.

Compiling dart for webassembly would be fantastic

Compiling dart VM to WASAM would also be interesting

Are there any updates here guys? 馃

WASM will speed up webgl-based applications.

How will it exactly speed it up?
This is entirely wrong. This may be the case in some near future, but not now.
Right now WASM and JS have the same peak performance.

How will it exactly speed it up?
This is entirely wrong. This may be the case in some near future, but not now.
Right now WASM and JS have the same peak performance.

@nlhnt your assertion is quite debatable,
today as average WASM + native (C / Rust) appears to be 20% faster than JS (source)
this uplift being worth rewriting a bunch of code base is definitely up to debate,
but the gain in performance is seems to be a fact.

Moreover comparing a relatively new technology against a super-optimized one
one may think that there's room for this gap to widen.

I'm not implying that WASM + Dart would reach the performance of C or Rust + WASM,
but a performance uplift could be expected

Could the experimental work that was done for compiling Dart with LLVM be used as the basis for compiling Dart to WASM?

The kind of use case that this may be useful for is something like the new Rive wasm runtime which was written in c++, but perhaps, given the other Dart based work Rive is doing, they may have chosen to write it in Dart if there had been a Dart->WASM compiler with a low overhead runtime?

Given the Dart on LLVM work was based off of Dartino, maybe it would have such a small enough runtime?

Could the experimental work that was done for compiling Dart with LLVM be used as the basis for compiling Dart to WASM?

Unfortunately not really for a couple of reasons - most importantly because LLVM backend would not be able to target WASM with GC, which is what we are interested in targeting - as opposed to targeting WASM linear memory and compiling our C++ runtime system to WASM. The second reason is that nothing based on Dartino should be considered usable at this point - Dartino comes from Dart 1 days and did not even entirely faithfully implement Dart 1 semantics (e.g. no support for reified generics).

That being said: given the recent effort (largely driven by V8 team) to implement and evolve GC support in WASM I would say that our interest in WASM as a target for the Dart language is also increased. I can't give any concrete timelines or promises - but I just want to say that WASM is actually starting to look like an interesting target.

On a tangential note: this was not the only experiment we have done with LLVM - we had intern project implementing LLVM backend for the Dart VM AOT compiler two years ago and most recently an engineer from Alibaba with LLVM background has implemented one as well. The practice shows that using LLVM does not really have any large benefits.

Great!!!, it would be fair and necessary

It would be interesting to perhaps redo the C / C ++ part of Dart and Flutter and bring it to Rust. So we would have something with a strong focus on security and performance. And maybe that way we would have Dart compilations in WASM that we would be sure are not going to do strange things or have security holes that make software maintenance so difficult.

For the moment and as long as there is no direct Dart compilation to WASM, we can use as an alternative to make modules in Rust which is Multiplatform and through Dart's FFI make calls from Dart / Flutter.

@mraleph thank you for the very comprehensive reply!

Given your previous comments on JS being a good target based on available built-in GC, it makes perfect sense about WASM.

And thank you for the extra info about the other LLVM experiments, happy to hear that current AOT compileris competitive or
better than LLVM and I guess given it already supports x64 and arm,I guess adding WASM generation would not be that prohibitive.

My main request for if/when Dart to WASM support is worked on would be: that there be a way of choosing to have a "minimal" runtime. Going by your previous answer to my asking about the VM runtime, I hope that excluding dart:io support, icu and WASM having builtin GC, it could mean that the Dart VM runtime could be quite small for a WASM target.

Dart is already compiled to JavaScript. So why not compile it to AssemblyScript (WebAssembly using Typescript) too! AssemblyScript has already implemented GC, WASM interop (via as-bind), generates small binaries, and it has already solved many of the issues.

https://www.assemblyscript.org/

You just need to add a few more things to the current Dart to JavaScript compiler like passing the types.

For example, this project already implements a Dart to TypeScript.
https://github.com/polymer-dart/dart2ts
https://github.com/polymer-dart

I haven't tried it yet, but with the help of this and AssemblyScript, wasm is already in the hands of Dart developers! These just need some attention from the core team.

Side benefit: If this is solved, Dart can also be used for targeting TypeScript!

You just need to add a few more things to the current Dart to JavaScript compiler like passing the types.

If you try to add these "few more things" yourself you will discover that JavaScript and AssemblyScript are two very different targets despite some syntactic similarities that latter has to TypeScript.

this project already implements a Dart to TypeScript.

This project implements subset of Dart to TypeScript, and a single pass AST conversion is not something you want to be doing really doing - the devil is in the details. That's why dart2js is hundred of thousands of lines of code.

You just need to add a few more things to the current Dart to JavaScript compiler like passing the types.

If you try to add these "few more things" yourself you will discover that JavaScript and AssemblyScript are two very different targets despite some syntactic similarities that latter has to TypeScript.

this project already implements a Dart to TypeScript.

This project implements subset of Dart to TypeScript, and a single pass AST conversion is not something you want to be doing really doing - the devil is in the details. That's why dart2js is hundred of thousands of lines of code.

Well writing a wasm compiler from ground up is much harder. That's why this issue has not had much progress since 2018.

I am trying to suggest a faster path to the target. The end users will certainly appreciate "a little more" progress on this even if it is based on a compiler that supports a subset of Dart. The quality can be increased over time if there is something that works partially.

The end users will certainly appreciate "a little more" progress on this even if it is based on a compiler that supports a subset of Dart.

Unfortunately we are not interested in a compiler that supports subset of Dart. We are interested in a compiler that can run actual Dart applications (which are usually thousands of lines of Dart code using most of its language features).

That however should not discourage you from building a compiler that supports subset and satisfies your particular use case. e.g. similar to how somebody built that dart2ts compiler you are linking to - which is far from something that we would ever consider doing ourselves.

You can't compile all the Dart applications to WebAssembly because WASM currently does not have WebIDL bindings (or if you use JavaScript interop, it will have a low performance like how Blazer tries to do so).

To fully compile all Dart applications, you need to wait for this issue to be resolved and then appear in the browsers. That seems like "a few years" from now.
https://github.com/WebAssembly/proposals/issues/8
https://github.com/WebAssembly/interface-types

The problem is that Wasm isn't targetable as it does not integrate a solution for garbage collection... Thus which limits Webassembly to low level languages being C / C++ / C# / Go / Rust and some others.

With Wasm 2.0 next generation languages like Python / Dart / D / Java could be used.
You can contribute to the proposal here https://github.com/WebAssembly/gc

The problem is that Wasm isn't targetable as it does not integrate a solution for garbage collection

I don't think that's actually correct. Rather it means the full DartVM along with it's GC needs to be included in the WASM which of course significantly increases the size.

Rather it means the full DartVM along with it's GC needs to be included in the WASM which of course significantly increases the size.

That's true. GC is just an algorithm that can be implemented in the wasm binary. The GC will take some space, but for example, AssemblyScript does that and it has one the smallest generated wasm binaries among the others.

https://github.com/dart-lang/sdk/issues/32894#issuecomment-684808186

That's true. GC is just an algorithm that can be implemented in the wasm binary. The GC will take some space, but for example, AssemblyScript does that and it has one the smallest generated wasm binaries among the others.

#32894 (comment)

You may start a Dart-to-AssemblyScript compiler project if you want, but remember that AssemblyScript is not a standard as Dart, WebAssembly, JavaScript, TypeScript and EcmaScript are!

I am calling the official AssemblyScript documentation here:

Also, both can make use of compiler infrastructure that has been created by many individuals and corporations over years. In contrast, AssemblyScript is a relatively young project with limited resources that strives to create a viable alternative from another perspective.

@StEvUgnIn

I am calling the official AssemblyScript documentation here:

Since the scope of your request is clearly different
I think your feature request should be in a separate issue,
rather than trying to hijack this one

Any public comments about the work going on here?

https://github.com/dart-lang/sdk/commits/wasm-backend

Any public comments about the work going on here?

Long story short: over the last 3 months we have hosted an intern who worked on targeting WASM+GC. He got some preliminary results: managed to implement enough of a backend working to translate a simple merge-sort benchmark. Unfortunately internship time has just run out. We are interested in driving this further, but right now we have no concrete plans, things are in discussion.

/cc @mkustermann

Glad to see Dart can be compiled into WASM~ +1
The browser as the desktop environment seems will happen very soon.
Dart to WASM (but not rely on another scripting language: javascript) seems more wisdom because javascript is not designed for big programs(at least that's why they now have typescript).

Another use case: I'd like to compile Dart to Wasm so I can write canisters that run on DFINITY's Internet Computer. Only languages that compiles to Wasm are viable, so Dart can not be used to create canisters for the Internet Computer until this support is added.

Was this page helpful?
0 / 5 - 0 ratings