stdweb icon indicating copy to clipboard operation
stdweb copied to clipboard

minimal example is 1mb in release mode

Open jaroslaw-weber opened this issue 7 years ago • 9 comments

Hey, I was thinking to use wasm in my project, but it is very small website and wanted to have fast load times. I tried compiling minimal example but I got 1mb file in release mode which is too much. Is here a way to optimise the size of the output?

jaroslaw-weber avatar May 01 '18 03:05 jaroslaw-weber

I built my own project and it was 300kb, not bad. Why the example was 1mb then? It was building directly under the "examples" folder so maybe it was including some other files? Still, how about adding some tips for wasm file size optimisation to the readme file? I was able to go down to 200kb with few flags from here: https://github.com/rust-lang-nursery/rust-wasm/issues/109

jaroslaw-weber avatar May 02 '18 01:05 jaroslaw-weber

Did you perhaps use one of the Emscripten targets to build the example? When I build the minimal example with cargo web build --release --target=wasm32-unknown-unknown I get a 318kB .wasm file.

Yeah, that can be further cut down with LTO, optimize for size, alternative allocator, etc. There is going to be a limit as to what you can do though as a non-insignificant chunk of Rust's stdlib has to go into the resulting .wasm file and there isn't much (currenty) you can do about it.

koute avatar May 02 '18 23:05 koute

Yes, I got it down to 210 kb with optimisations. Not bad, but for small projects its too much. I wish there would be a way to get this down to at least 100kb.

https://users.rust-lang.org/t/compile-rust-to-target-wasm-how-to-strip-to-300bytes/15450 Some people stripped basic wasm file to 40kb. So I guess remaining 120kb is stdweb (i have also toml crate but it is very small)? I failed to make cargo bloat work with this. I would really enjoy "lite" version of this library.

jaroslaw-weber avatar May 10 '18 08:05 jaroslaw-weber

@jaroslaw-weber Keep in mind that most of that 210 kb is code from the Rust standard library. As your program grows larger and larger, the standard library will stay roughly the same size.

So if you make your program 5 times bigger, it won't grow to 1050 kb, instead it'll more likely be ~300-400 kb. I have a Rust program with ~5,000+ lines of code which compiles down to 555 kb of wasm.

You can think of it as being similar to using jQuery: you pay a one-time cost of loading jQuery, and that's it. No matter how big your program gets, jQuery will still be the same size.

So if you compare Rust to a very small JS program, then you'll be disappointed. But if you instead compare it with the various JS libraries that people use (jQuery, Lodash, etc.) you'll find that the Rust code is quite comparable for size.

And I think if you compare a large Rust program to a large JS program, the Rust program will probably be smaller (or at least be similar in size).

Some people stripped basic wasm file to 40kb. So I guess remaining 120kb is stdweb (i have also toml crate but it is very small)?

I don't think the 120kb is from stdweb. The reason they managed to get their program so small is because their program doesn't really do anything: it doesn't panic, it doesn't allocate on the heap, it doesn't use vectors, it doesn't use strings, it doesn't use JS objects, etc.

As soon as you do anything even slightly complicated, the size will go up a lot, because Rust now has to include code for creating/managing/destroying vectors, code for creating/managing/destroying/serializing strings, code for panicking, code for the allocator, etc.

With JS, the browser handles things like allocation, strings, arrays, exceptions, etc. So the size of your JS program is small.

With Rust, it manages everything itself, so the compiled wasm has to include code for allocation/strings/vectors/panics/etc.

Rust is very good about only including the code that you actually need, so in general there's very little bloat. The primary sources of bloat are inlined functions and monomorphization of functions. Both of those things can be controlled in various ways in Rust (e.g. disabling inlining, using trait objects, etc.)

There is some work going on to reduce the size of the Rust standard library (in particular, removing the error message stringification code). You can also swap out the default Rust allocator with a much smaller (but slower) allocator.

Pauan avatar May 10 '18 14:05 Pauan

P.S. You might have success using twiggy to analyze why your wasm file is so large.

Pauan avatar May 10 '18 15:05 Pauan

@Pauan Thanks for the very long explanation. I understand that there is nothing much to do about it, I was just hoping there was some way to drop the size a little.

I guess you can close this issue, but I was also thinking about adding this information to README (together with some size optimisation tutorial) for people starting with wasm and trying to make the output smaller :)

jaroslaw-weber avatar May 11 '18 04:05 jaroslaw-weber

@jaroslaw-weber The most comprehensive "how to make your Rust wasm small" guide is a part of the Rust Wasm book.

You're right: it might be useful for stdweb to link to it in the README.

Pauan avatar May 12 '18 01:05 Pauan

Support for WASM optimization would ideally be added as part of the parcel plugin.

bgourlie avatar Jun 04 '18 03:06 bgourlie

Also keep in mind that wasm compiles much faster than javascript. At least Firefox with its new streaming compiler can compile really fast.

athei avatar Jul 11 '18 22:07 athei