Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebAssembly support #737

Closed
GerjanOnline opened this issue Mar 1, 2017 · 37 comments
Closed

WebAssembly support #737

GerjanOnline opened this issue Mar 1, 2017 · 37 comments

Comments

@GerjanOnline
Copy link

Now that WebAssembly is out of preview (https://lists.w3.org/Archives/Public/public-webassembly/2017Feb/0002.html), is this something you consider as an alternative output?

Personally, I think it can give F# a head start and maybe drive the F# adoption as a whole. You guys have done incredible job by building this "new webstack" but supporting WebAssembly may give it an extra enormous boost.

It is just a question, I have not read the specs of WebAssembly and did not look at the limitations. I am just curious what you think about this matter.

@alfonsogarciacaro
Copy link
Member

alfonsogarciacaro commented Mar 1, 2017

There seems to be a lot of hype (and confusion) about WebAssembly ;) I've read a bit about it, but I haven't fully understand it yet and even if it's out of preview now (which just means browsers can enable it by default), I don't think it means that WebAssembly is already a finished product.

According to its high level goals right now WebAssembly only has the same functionality as asm.js, and if you look at its specs you'll see that's mainly designed to crunch numbers: only numeric types (no string, etc), no garbage collection, etc. This makes it very difficult to target WebAssembly from a higher level language like F#. For reference, see why Typescript cannot be compiled to asm.js.

The goals also say that there'll be more features coming and support for other languages than C/C++. I think also Icaza commented they want to port the .NET platform to WebAssembly someday. So I guess it's in the horizon, but we still have to wait :) Anyway, now that WebAssembly is supported by the browsers, there'll be more libraries coming for intensive computations and you should be able to use them from F#/JS.

@GerjanOnline
Copy link
Author

Thanks for your answer, I also read scala-js/scala-js#1747 that was also mentioning the lack of GC.

Conclusion is: little more patience :)

@alfonsogarciacaro
Copy link
Member

alfonsogarciacaro commented Mar 1, 2017

Yes, we must wait. But that's OK, we programmers are always waiting for the "next big thing" :)

Anyway, although any performance promise is always very appealing, take into account that the main benefits of WASM will be in the parsing and compilation times, which are not that bad for most applications (and JS execution performance in V8 keeps getting better and better). And as commented above, I'm pretty sure that there'll be many libraries coming for computational intensive tasks that'll you be able to consume from your JS/F# apps (three.js comes to mind).

@jslegers
Copy link

jslegers commented Jun 22, 2017

I understand that TypeScript is not intented to be compiled to asm.js, C/C++ or WebAssembly (and I expect that), the ability to export a language like Flow or TypeScript to typed AST in some way or another would be a good first start. With the TypeScript core devs not interested in this feature, it would at least open up the possibility for other teams to implement TypeScript to WebAssembly, TypeScript to C/C++ or TypeScript to asm.js conversion wherever possible.

@jslegers
Copy link

jslegers commented Jun 22, 2017

Those also interested in converting staticly typed variations of JavaScript to asm.js, WebAssembly or C might want to take a look at ThinScript, TurboScript or AssemblyScript.

ThinScript compiles to JavaScript, WebAssembly, and C. TurboScript compiles only to JavaScript and WebAssembly. AssemblyScript compiles to WebAssembly only.

Each of these languages have been inspired by TypeScript, and the latter is a subset of TypeScript.

I'd like to thank @RReverser for pointing me in the direction of these languages.

@alfonsogarciacaro
Copy link
Member

@jslegers Now that's something very interesting 😉 If we just have a language very similar to typed JS/Typescript it should be easy to target it using Fable. We just need an AST specification like this one and a function to transform that AST to actual code.

@jslegers
Copy link

jslegers commented Jun 22, 2017

I like where TurboScript is heading :

AssemblyScript is only two weeks old, so it's still too early to see where that one is heading... but that one sure does look promising as well!

@ShalokShalom
Copy link

Any news?

@alfonsogarciacaro
Copy link
Member

@ShalokShalom Compiling Fable to WASM is not a priority at the moment, if it happens it would be, as discussed above, compiling to a JS-like language that targets WASM. Apparently the languages mentioned above haven't evolved much so I'm not sure. Recently I had a look at https://github.com/ballercat/walt but it seems to also be in an early stage too.

You may also want to have a look at https://github.com/ncave/dna-redux

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 16, 2019

https://caniuse.com/#feat=wasm

Most browsers now support it by default. Rust compiled to wasm seems to be of fairly easy todo as of now.

@ncave
Copy link
Collaborator

ncave commented Dec 16, 2019

@7sharp9 A possible path forward (aside of completely rewriting Fable to target Rust, which is a large undertaking) will be to produce output that AssemblyScript can consume, and rewrite the Fable BCL to target it too. Unfortunately AssemblyScript is still missing important features like closures and iterators.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 17, 2019 via email

@ncave
Copy link
Collaborator

ncave commented Dec 18, 2019

@7sharp9 In theory should not be that big, once it supports a sufficiently large subset of javascript.
But as usual In theory there is no difference between theory and practice. In practice there is.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 18, 2019

Rust targets wasm but also seems to have quite advanced support, I think all sorts of rust syntax can be represented. e.g: https://rustwasm.github.io/wasm-bindgen/examples/closures.html

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 18, 2019

@alfonsogarciacaro From some study in certain areas it seems a wasm solution could be around 40% faster on desktop and even up to 60% faster on mobile devices. I just benchmarked some cpu emulator code and it was 47% faster than a typescript implementation. Its food for thought anyway.

@voronoipotato
Copy link
Contributor

voronoipotato commented Dec 18, 2019

Is performance actually causing issues for end users currently? While cool and interesting, this definitely sounds like a nice to have. Someone should work it, but that someone in my opinion shouldn't be the core team...

@MaxGraey
Copy link

MaxGraey commented Dec 18, 2019

@7sharp9 Closures in Rust and JavaScript are pretty different. I suggest read this article: https://stevedonovan.github.io/rustifications/2018/08/18/rust-closures-are-hard.html

@ncave
Copy link
Collaborator

ncave commented Dec 18, 2019

@7sharp9 See also #1601.

I haven't actually looked into generating Rust from AST, so I may be completely wrong, but I tend to agree with @alfonsogarciacaro that a Fable port to target Rust would be a larger effort, as I'm not sure how much of the Fable code base can be reused. Of course that shouldn't be stopping anybody from trying it, if they have the time.

IMO (only), as discussed above, in terms of effort an easier path forward to support webasm as a target without changing Fable too much can be explored in 2 gradual steps:

  1. First, target TypeScript with strict types (not any), see [Help Wanted/Design] Improve TypeScript integration #1887.
  2. then target AssemblyScript, working around missing features.

Some missing features like closures can be worked around by lambda lifting, others like iterators we have to figure out if their usage can be replaced.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 18, 2019

@voronoipotato It depends if 40% increase in desktop and 60% increase in mobile speed is important to you. You could re-quantify this to saving money on cloud due to being more efficient.

@voronoipotato
Copy link
Contributor

@7sharp9 Right now, for me it's not but I imagine that could make a big difference to some people. For the record, I do think someone should work on it, I just also have concerns that if the core fable team worked it that they would become spread too thin. Perhaps if someone could spearhead an effort that others could contribute to (not implying you, obviously).

@Zaid-Ajaj
Copy link
Member

Zaid-Ajaj commented Dec 18, 2019

I don't see why it is even interesting for Fable to compile down to Wasm in the first place. Fable is great because of interop with JS and the ability to use the vast javascript ecosystem from a typed language such as F#. Assuming that this wasm target will be implemented, you wouldn't be able to compile JS bindings to wasm because they are not typed (try writing any Fable app without bindings and tell me about your experience)

If you are aiming to "run F# on wasm" then Bolero is much more interesting solution that already exists, works and maintained.

I think it is far more interesting to focus on how to make Fable easily consume wasm modules for use from within Fable application (again, integration ftw) and write docs with examples for that.

@voronoipotato
Copy link
Contributor

voronoipotato commented Dec 19, 2019

I guess you don't have to deal with the .net runtime environment, which does sound kinda interesting. Makes it almost like KreMLin.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 20, 2019

@Zaid-Ajaj Well Im the opposite, I don't know why you would not be interested in having Fable be able to compile down to wasm. I don't think I would want to use anything razor oriented like Blazor.

@ShalokShalom
Copy link

You mean Bolero?

Where do you see the benefits of a Fable specific implementation?

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 21, 2019

Where do you see the benefits of a Fable specific implementation?

By giving F# syntax WebAssembly benefits.

@alfonsogarciacaro
Copy link
Member

Unfortunately, I'm not sure Rust->WASM benchmarks would be comparable to an hypothetical F#->WASM with Fable, as this would require to include some garbage collection mechanism (which is out of scope for Fable anyways). For reference, please see this article (Garbage Collection section) or this comment. Until WASM includes an efficient garbage collector, the best (and only) solution to compile F# to WASM is Bolero.

This is a bit off-topic, but I've been considering several languages that could be targeted by Fable (taking in consideration that Fable is basically just a syntax translator with some code injection), and my conclusion is right now the most valuable one would be Dart.

  • It's very similar to C#/.NET, so it looks like it shouldn't bee too difficult to adapt Fable to it (easier said than done).
  • Dart uses an import mechanism similar to modern JS, so they way of making Fable bindings should work more or less the same (hopefully better, because Dart libraries are typed).
  • It would give access to Flutter, which would be a very interesting alternative for mobile development to Xamarin and React Native. Flutter team is also working to include cross-platform desktop and web targets. And Flutter uses a declarative UI similar to React which is familiar to Fable developers (I believe Elmish could also be adapted).
  • Dart provides now cross-platform AOT compilation, which again should be an interesting alternative to .NET Core self contained executables (at least I expect the file size to be smaller).
  • If Dart continues to raise in popularity, we could expect it to target WASM at some point. Although according to the thread link above, this doesn't seem to be a priority for the Dart team atm.

I've been considering to start working on this. But it would have to be a professional project for me now, so I'd need to find some sponsors or collective funding in order to allocate time for it.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 23, 2019

I think its unfortunate that the F# language cant be established in this area, apart from the Bolero/Blazor oriented type ideas which for me doesn't mesh particularly well with the whole concept of WebAssembly in its performance oriented idiom. I guess Rust is a perfect fit which is why there is so much activity in this area especially with respect to linear allocation and performance computing. I think F#/Fable would bring an elegance of language to WebAssembly its just the current ecosystem of F# is not so good a fit.

@MaxGraey
Copy link

MaxGraey commented Dec 23, 2019

Why doesn't just use LLVMSharp binding and compile direct to LLVM IR? See this as basic example

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 23, 2019

Such a thing would be an interesting concept, Im guessing the GC oriented aspect of F# is where there would be trouble as @alfonsogarciacaro stated.

@MaxGraey
Copy link

LLVM GC

@Luiz-Monad
Copy link

Luiz-Monad commented Dec 23, 2019

Porting Fable to be a native compiler instead of language transpiler would be too far off from what it does, it would be like an entire new F# compiler, and environment, that's too low level. Fable is not a backend compiler that target a virtual machine.
But the TypeScript or Dart path looks like a good alternative.
Fable should remain a transpiler, but adding support for other languages like Dart would solve the problem with having to implement the environment, you just run on top of another language (as we already do, although Babel could be a problem).
That keeps the usefulness of Fable, otherwise we already have several ways to natively run F#.

I will be using both DNA-redux and Fable in my porting of the React that I'm planning to do, because I'm done with using JS renders on top of Elmish, I want something custom.
(Inferno is pretty small, the real problem we have to solve is Tree-Diffing, the other things that React does are incidental to the way JS is used)
I'm thinking about using DNA to optimize the hot paths, so I need both a "native" WebAssembly compiler and a High-level Transpiler.
What's blocking me from doing this, is that WebAssembly has no native support for accessing the DOM, and I think the overhead would make it useless, so first we only need a fully F# React Implementation. something like "Freact" for F# react transpiled to JS.
And the Garbage Collector is not an issue, we can use some C++ GC library compiled to WebAssembly by the Emscriptem LLVM compiler, real problem is WebAssembly interop is still shitty, that makes it less useful for non-numeric processing.

@alfonsogarciacaro
Copy link
Member

@Luiz-Monad There's ongoing effort already to create a tree-diffing in F# for Fable (well the approach is somewhat different): https://github.com/krauthaufen/Fable.Elmish.Adaptive

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 23, 2019

Maybe the llvm output from F# via out could be used for a rust like wasm experience...

There is a lot of stuff going on in the wasm area, this was interesting: https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/

@ncave
Copy link
Collaborator

ncave commented Dec 23, 2019

@Luiz-Monad Heyo! An actual user of DNA-redux, respect!

Unfortunately it shares some of the downsides of other dotnet based interpreter runtimes compiled to webasm, namely lower performance than direct webasm code (until webasm gets a JIT), which negates some of the webasm benefits, and also it runs regular F# dotnet binaries (which tend to be on the bigger side), but with the upside of it being relatively easy to tinker with the runtime.

Those are conflicting goals, obviously, (smallest webasm code vs webasm performance vs smallest overall dist bundle), so some forms of AOT compilation to webasm will probably do better than others on that spectrum. There was an article on the net comparing webasm code sizes produced by different compilers.

@7sharp9
Copy link
Collaborator

7sharp9 commented Dec 23, 2019

Yeah a Rust Hello world is 864 bytes including version metadata. A C# one was 2.4MB with all the aot jangly bits rattling around in there.

@MaxGraey
Copy link

MaxGraey commented Dec 23, 2019

You could compare wasm size in this project: https://boyan.io/wasm-wheel. C# Dna take ~180 kb for glue code and ~150 kb for wasm which is not bad. wasm modules from mono usually takes several megabytes

@ShalokShalom
Copy link

ShalokShalom commented Dec 25, 2019

It would give access to Flutter, which would be a very interesting alternative for mobile development to Xamarin and React Native.

Qml.NET is another alternative. GPU acceleration, desktop support, designing the GUI without coding at all and so on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants