Hacker News new | ask | show | jobs
by montroser 1434 days ago
More of a comparison between WebAssembly and JavaScript, really. That the WebAssembly was compiled from Rust is not especially meaningful here.
6 comments

From the user-experience perspective, it matters that it is Rust. Unless you directly write WASM code, which is rarely (ever) the case.

Rust is a language that compiles to WASM. Sure, there are other options to compile to WASM, but they differ by interface (programming language, library, tooling) and (likely to a lesser degree) - performance.

Given the title I had expected this to be a comparison between the js and rust in terms of development, not performance. I learned nothing new about rust by visiting this page. All I learned was that compiled WASM is faster than js.
> All I learned was that compiled WASM is faster than js.

You learned that Rust compiled into WASM is faster than JS. That won't be the case for every language. (We had an example yesterday on the front-page where it wasn't. Ironically, its title implied that it was a generic comparison with WASM.)

> From the user-experience perspective, it matters that it is Rust.

From the user-experience perspective, none of the page loads without javascript, so it is all javascript from a customer's perspective.

I wouldn't say the source language is not meaningful. If you wrote an ahead-of-time JavaScript-to-WebAssembly compiler and benchmarked the WASM generated by that, it would probably be a lot slower than the WASM generated by the Rust compiler, no?
Has anyone compiled v8 to WASM so we can finally run JS in the browser? ;)
v8 is a JIT engine, WASM would not support it.

JavaScriptCore has been compiled to WASM though:

https://mbbill.github.io/JSC.js/

People usually ask why, the answer is usually for fun or for sandboxed plugins.

I imagine that, if one were feeling extremely masochistic, one could generate WASM, JIT-style, and load it as needed. The result may not perform well.
I assumed the JIT would emit WASM.
please don’t give them more ideas
True, but if you where in a front-end project doing JS with some WASM parts that happened to use Rust for the WASM, you'd probably not ask yourself "JS or WASM?", you'd ask yourself "JS or Rust?" when deciding where to put some logic.

And I'm not sure if we can assume that all languages that offer compilation to WASM would be roughly "rust fast": I wouldn't be surprised if we already had some examples that aren't really good matches for that tight inner loop case you might want to wasmify. Perhaps there are already some that just want to get the "runs in browser" checkbox ticked?

Not sure, it could also be viewed as a comparison of ahead-of-time compilation vs. just-in-time compilation (I guess the code paths are hot enough to be completely "jit-ed" here), and then the compiler isnt irrelevant at all.

But havent looked into the details on how much difference that alone makes in this case.

I think its also a testament on how fast JS has gotten.

The fact that it was written in Rust (or any other non-VM lang) is meaningful because programs written in a Language that needs a VM (All the GC'd languages for example) need the vm to be shipped as well. Thus, making the WASM-program larger and slower.
Go is a GC language, but it doesn’t need a VM. It’s a native, statically linked binary that contains the Go runtime.
Maybe Runtime or Runtime System is a better word than VM? Go has _something_ that manages Go routines and GC and so on.
Sure, but Rust can have a runtime, and presumably Rust on WASM does.

If you don't have a runtime in Rust you only get core.

https://doc.rust-lang.org/core/

This has obvious effects (you don't have an allocator so you can't have String) and more subtle effects (your slices don't have a sort() method! However they do have a sort_unstable() method) but while it's probably a reasonable environment for the firmware inside a custom $25 gizmo it's not a very comfortable one for general purpose programming.

To deliver a bit more, for example an allocator, you're bringing in a bunch of platform specific code, which, just like the Garbage Collector for Go, you did not write.

IIRC every higher level language has some runtime, even C. Question is, how trivial/substantial is it?
Like Rust, C defines what happens if you don't have its rich standard runtime, you get "free standing" C.

C's free standing mode is even thinner than Rust's core, because it doesn't supply a library of code, you just get the primitive types, the operators and the language features that don't involve any libraries. To give a very concrete example, Rust's core depends on memcmp() existing, Rust assumes your toolchain knows how to memcmp() on your target architecture inherently, but in C you could write memcmp() if you had to. You won't these days, because your C compiler invariably provides this feature, but in principle you could.

In principle C++ also defines a "free standing" mode, but it's a mess and so people don't write for C++ free standing mode in the real world. C++ in an environment where you can't have the actual standard library is likely to be specified in terms of which features from the standard library you can have and which you cannot, for each such environment. For example maybe you can have threading but no filesystem APIs, or you can have a heap allocator but no threads.

You'd need a runtime for managing green threads even if you didn't have a language with GC.
And that distinction is completely meaningless. It still has to replicate the runtime, the same way as any other managed language.
Since we're being pedantic, all mainstream languages (even Rust) have a runtime, so your "managed vs unmanaged" language distinction is completely meaningless. :)

If there is a salient distinction, it's whether the runtime is easily and practically distributed as part of the compiled artifact, which is true for C, Rust, Go, etc but not so much for Python or JS (nor probably Java or C#, although there are efforts for static, native compilation for those platforms which probably come with significant caveats).

and because that statically linked runtime does a lot of things, it contains a lot of code and adds a megabyte or two to the final WASM product: https://dev.bitolog.com/minimizing-go-webassembly-binary-siz...

Larger runtimes not only add bloat to the final WebAssembly, but they also can make interoperating harder because they often require more (i.e. any) bookkeeping when sending stuff back and forth.

also worth mentioning is that this is why people build projects like TinyGo and MicroPython – they love the language, but can't work with the trade-offs that the designers chose

> also worth mentioning is that this is why people build projects like TinyGo and MicroPython – they love the language, but can't work with the trade-offs that the designers chose

It's not like small runtimes are fundamentally better in this regard. They work better for constrained environments, but they often make tradeoffs which are inappropriate for other use cases. It's hard to make a runtime that works for everything, and it's not necessarily even a worthwhile goal--you can use TinyGo when you're working in a constrained environment, use Go when you're not.

But Go compiled to WASM does (or some kind of runtime).
The language whose compiler generated the code is relevant, as it often constrains what the generated code look like in broad terms.