Webassembly vs JS performance

Hi there

I have the feeling something is wrong with this small project I have compiled.

I've created a small project to generate a fuzzy time based on two dates in seconds. It can be found here https://gitlab.com/memborg/fuzzy_time

When I time how efficient JS and WASM is, WASM looses by a factor 10 when a million fuzzy times are generated.

A sample of a single run with a million random dates.

js.fuzzy_time: 1879ms
JS average 0.001096 millisecond 
wasm.fuzzy_time: 15579ms
WASM average 0.014035 millisecond

The average time for both JS and WASM is the average time it takes to generate a single fuzzy time.


Firefox performance snippet

Am I drunk or is it reasonable to asume that the overhead for marshalling from JS to WASM will generate this kind of overhead?

At a guess the conversion of the string from rust to JS would be a substantial part.

Forgot to mention that everything relies on https://github.com/rustwasm/wasm-bindgen.

Would it be better to take it up with them?

In addition to what @jonh mentioned (which may mean that this is a microbenchmark that wasm simply can't really do that much better on) your build script doesn't pass --release so you're testing a debug build of Rust instead of an optimized build.

3 Likes

i also think this is caused by the wasm↔js marshaling overhead; this puts a minimum on the granularity of work for which it is efficient to call out to webassembly

your function is likely performing too little work to be worth it

to know for sure: what happens if put a benchmarking loop inside the rust code?

2 Likes

The quick and dirty way to get cost of string conversion is to change the functions to just return the length of the string.

You're probaly right. My rust functions is doing too little work ake any difference and that is a valid point in when to use WebAssembly and not.

Well, doing a --release build reduced the overhead to a factor 5 instead of a factor 10 when building a without it.

A good thing to remember when doing webAssembly.

1 Like

Thank you all for your great input.

This has been educational and I begin to understand what and when Rust/webAssembly will come in handy.

seems relevant to this: for newer versions of Firefox this overhead is going to be reduced and "calls between JS and WebAssembly are faster than non-inlined JS to JS function calls"

https://hacks.mozilla.org/2018/10/calls-between-javascript-and-webassembly-are-finally-fast-🎉/

3 Likes

To clarify, though, note that that only applies to the actual call from JS into WASM. With wasm-bindgen, if there are strings or other non-primitive types in a function signature, you're not calling WASM directly but going through a generated wrapper function that converts those types, and that work will be just as expensive as before.

1 Like

thank you, yes i wondered about that, whether they optimized only the calls themselves or also special-cased argument copying—which is a large part of overhead with web-sys because so many DOM functions take strings—so apparently not (yet)!