From a WebAssembly Perspective
assemblyscript.org
assemblyscript.org
There are a lot of other languages coming to wasm. It looks like garbage collection is stabilizing. E.g. jetbrains released an experimental wasm compiler for Kotlin recently that uses that. Currently that only works if you launch Chrome with some experimental flags to enable the feature. But at some point that will be generally available there, and in other browsers.
So, whether you are using C#, Kotlin, Swift, Crystal, or any other garbage collected modern language, chances are there will be a wasm compiler for it soon (if not already) and rich ecosystem of libraries and tools. I see this as a matter of time. Right now it's all a bit cutting edge. So, the whole space is dominated by languages not in need of garbage collection (C, C++, Rust, etc). However, that will change pretty soon.
E.g. Swift and Kotlin are already used for modern UI development on mobile. Using those languages in a browser makes total sense. Kotlin actually has a js transpiler and there are some Kotlin specific web frameworks that I've used. With wasm and the inevitable emergence of new UI frameworks targeting wasm and browsers, there might be a little renaissance in web ui development. Things like Figma prove that web uis don't have to be laggy, limited, and driven by css & dom trees.
Yes it adds up to the runtime size, still most implementations can be eventually trimmed down to similar sizes of typical SPAs.
Runtime size can be an issue; though arguably WASM is going to outperform minified javascript probably for the same code.
Typical SPAs only manage to stay small by simply not using a lot of run-time dependencies. The same trick will work with wasm. If you don't need it, don't depend on it. Simple. Or alternatively, trade off not having to reinvent the wheel against a few MB of dependencies. In an age where people watch 4K youtube videos, pulling in a few MB is not that big of a deal anymore.
And incidentally, the lack of any sizable run-time dependencies also makes replacing those not that big of a deal. E.g. most of the React ecosystem involves a lot of compile time dependencies (hundreds of MB typically) but not a whole lot of run-time dependencies that people actually ship with their applications. A few hundred kilo bytes typically. I've used alternatives for React that only measured a few thousand lines of code. There's not a whole lot that those run-time libraries actually do that is that essential.
I've noticed with Kotlin js that there isn't a whole lot that I need or miss. Actually, even just having the Kotlin standard library is already a big upgrade relative to what browsers and Javascript have without any dependencies added. Add co-routines to the mix and few other multi platform libraries (e.g. kotlinx.serialization, kotlinx.datetime, ktor client) and it starts feeling like any other modern Kotlin stack that I've worked with. Except it all works in a browser. Is there a size penalty. Yes. Does it matter that much. Not really.
Might allow for a more powerful IPC too; where malloc'd objects can be transferred?
I am not convinced about that for two reasons:
1. Good money has been invested into making JS fast. If you look at actual benchmarks it is currently quite easy to end up in a situation were your WASM-based solutions might perform WORSE. So at least for now the performance advantages are not that great to begin with.
2. On the frontend, you still need JS to use the DOM. Getting data back and forth from JS to WASM can become a bottleneck. Plus rare processing speed is rarely an issue on the frontend and IO-bound stuff is something JS is already good at.
If you don't do frontend stuff, you don't have to use WASM, you know? You could just go native binary in the first place especially as modern languages have great cross-compilation support. (Edit: If you are after performance mainly and don't care about sandboxing and other advantages.)
Yes, if you need to do some image processing on the frontend or want your users to mine crypto for you, yes WASM has already uses but generally I am a bit skeptical.
Now WASM is awesome for getting you the C/C++/Rust world in the browser, sure. The performance improvements might be overrated though considering the additional development costs compared to just using JS.
(That was more a dig at the WASM hype in general, of course. Not meant to throw any specific shade at AssemblyScript. Still an interesting project regardless.)
2. This is planned to change with Interface Types which will let you call any DOM method from any wasm code without without custom bindings and performance hit as well as, for example, calling a python module from golang for example (as long as both are compiled to wasm)
I recommend this article about it: https://hacks.mozilla.org/2019/08/webassembly-interface-type...
> If you don't do frontend stuff, you don't have to use WASM, you know? You could just go native binary in the first place especially as modern languages have great cross-compilation support.
the main point of wasm outside of browsers is sandboxing and compatibility, a whole set of applications become possible when you have that. A simple example are SaaS application that let users upload wasm plugins that run on the SaaS application servers
> If you don't do frontend stuff, you don't have to use WASM, you know? You could just go native binary in the first place especially as modern languages have great cross-compilation support.
wasm is just one part of the puzzle, the other one is WASI which is poised to become a standard interface for OS interaction. With it you could conceivably have a single binary for any OS+processor architecture (as long as there is wasm runtime + the parts of WASI required by your app implemented). This is huge for embedded development, I myself spent insane amounts of time trying to get shit compiled to different OS+architecture
- Cross-compiling is perhaps easier these days, but it's still a pain to set up and takes time to compile
- WASM has compelling sandboxing abilities, I can see myself choosing a slower sandboxed client tool vs native binary, in particular to try out new stuff
WebAssembly is excellent for:
- Game's scripting engine (UE plugin example: https://www.reddit.com/r/unrealengine/comments/na6hfx/integr...)
- Rule engine for ServerLess scenarios (See Lucet)
- For node.js plugins instead native plugins. Webpack uses AS for hash calculations: https://github.com/webpack/webpack/tree/main/assembly/hash
- For smart contracts of blockchain. AssemblyScript uses for Near Protocol, The Graph Protocol, Cosmos and many others
> Computation-heavy logic like image manipulation, hot game logic, specialized algorithms, emulators, compilers and the likes are great use cases for WebAssembly, and as such for AssemblyScript as well. In some situations it may also be preferable to ship bytecode instead of minified JS, or just the ability to utilize a TypeScript-like language may open up new opportunities, for example for embedded scripting or plugins.
That doesn't really answer the question of why you would want to use AssemblyScript instead of eg C++ or Rust.
It's not as if you get any of the benefits of Javascript, except for a familiar syntax.
Ideally targeting WebAssembly from C and C++ compilers should be a -march switch, and Emscriptem would fade out.
https://github.com/schellingb/wajic
It's basically clang plus wasm-opt and some magic pixie dust which enables some of the most important features of Emscripten, but without the whole 'technology zoo' :)
Basically, the question "when targeting WASM, why should I use C++ and Rust instead of AssemblyScript" is just as valid.
In the end the language choice is most likely enforced by what libraries one needs to use for a specific project anyway (e.g. if you need to build a project on top of a handful C++ libraries, it's probably a good idea to use C++ for the whole project too - and at least there is such a choice now when targeting the web).
> Basically, the question "when targeting WASM, why should I use C++ and Rust instead of AssemblyScript" is just as valid.
…but, if you want to write typescript then why not just write typescript?
If you want better performance surely tier 1 support for wasm, for example, for typescript, it a categorically better solution for everyone, with no need for an entirely new language?
A good comparison is rust-gpu: this is an approach to let you write gpu shaders in rust. The toolchain is different, but you write rust. You compile it. It runs on gpus.
Not everyone needs, or wants to do this, but for people who need a) very high performance, b) existing tooling, you can do it, and it saves you writing shaders in c.
When rust releases a new version, the same rust compiler compiles new rust code and new rust syntax for gpu.
So… the parallels are clear, except assemblyscript seems to have missed the boat by deciding to invent a new language with high level similarity but not quite the same” semantics.
..and when typescript continues to evolve? Will assemblyscript forever be playing catch-up to new typescript syntax? Or fall behind the rentless march of the Microsoft/typescript release cycle?
What about when Microsoft decides to make this a first class feature of typescript itself? I think that’s not really that unlikely if it means significant performance gains.
I feel this is a missed opportunity. What you wanted was to be able to compile typescript to wasm, not a new language.
Assemblyscript is essentially a very restricted, low level variant of TS.
If you really want JavaScript in WASM, you can already get that by using Spidermonkey compiled to WASM as an interpreter. A compiled version of TS could be interesting, but would be a lot of work and would come with a lot of difficult challenges for getting could performance.
I will say though that I'd much rather use Rust than AS though, so I do see how the language has limited appeal.
There is something to gain from writing in a much lower level language though, be it C, C++, Rust, or, yes, AssemblyScript.
https://github.com/microsoft/TypeScript/issues/9202#issuecom... https://github.com/microsoft/TypeScript/issues/10386#issueco... https://github.com/microsoft/TypeScript/issues/375#issuecomm...
The only real difference with assembly script is that it's a garbage collected language. Otherwise, it uses llvm and the same set of optimizations you'd be getting with C++ and Rust.
Or do they? Unlike Assembly Script, Rust and C++ use LLVM, which is a lot better at optimizing than binaryen.
A more interesting question is instead: does AssemblyScript allow the same control over memory layout as C, C++ or Rust?
> does AssemblyScript allow the same control over memory layout as C, C++ or Rust?
There's no UB, so in a way AssemblyScript is almost more low level than those, as you have full control over the memory and instructions.
Hmm ok, yeah. C++ with heavy stdlib (or generally: template) usage has the same problem (although in my experience it's more like 10..20x slower), but OTH C's debug and release build performance is usually much closer. I guess it's a side effect of generics that they heavily rely on the compiler optimization passes to turn the resulting 'generic mess' into something closer to what a human would write (e.g. remove all the redundant and dead code resulting from 'template resolution').
It isn't designed for or suitable for large projects.
The other reason to use it is that it's much closer to WASM than Rust or C++. It's the closest you can get to writing WASM without writing WASM.
Why? The compiler itself is written in AssemblyScript and is capable of bootstrapping. The AS code base is quite large. In addition, there are other quite large projects. For example: https://github.com/acutmore/type-off. It's port of "sucrase" project (which functionally equivalent to esbuild or swc)
i32.ctz(...)
f64.reinterpret_i64(...)
i64.load32_u(...)
I didn't realize that was possible in WebAssembly/AssemblyScriptMakes it a great target! Which I guess is what it was designed for :)
I’ve had AssemblyScript recommended to me for exactly these reasons, but the one thing Go does have is a pretty great library ecosystem that AssemblyScript lacks.
importing stdio printf gives almost no added binary size
importing iostream cout << adds like 5mb to the final .wasm file from what I remember. I asked around and apparently it pulls a whole sort of random stuff into your binary like internationalisation and currency conversion (dots vs commas)
Your native binaries do that as well, you just don't notice. Unless the compiler can offload some of these things to the OS-specific libraries
Constraint: has to be production-ready or very near production-ready.
I think I've heard of people using Go wasm in production but not 100% sure.
Context is App/UI development.
I am still to make sense of it.
Lovely.