I target regular binaries and wasm. Today I learnt running wasm outside the browser is a thing.
No idea if this is sensible, but wondering if this might be a good fit for mobile.
I target regular binaries and wasm. Today I learnt running wasm outside the browser is a thing.
No idea if this is sensible, but wondering if this might be a good fit for mobile.
Yeah, the only way to avoid this is by (1) using a language that at least makes it possible to do things without a large standard library or “runtime” backing it, and (2) carefully writing all the code to avoid anything that would result in large amounts of wasm anyway, including leaving many things to Javascript / DOM. This is a very annoying way of programming, and requires constant vigilance and corner cutting. While it’s possible to write Rust code that does something non-trivial and compiles to a few hundred bytes of wasm, most programs are going to pull in some libraries or built-in functions that raise the “size floor” quite rapidly.
As an IF-centric example: I’ve been working on a Glulx interpreter (which I keep bringing up here despite not being ready to release it – sorry!) that can be compiled to a wasm module and talk to a JS Glk library. Despite omitting the Glk library entirely, the wasm module was many hundred kilobytes (late edit: details[1]) when I started paying attention to its size. Through a long series of changes shaving off kilobyte after kilobyte, I got it down to 158 KiB right now. That’s not terrible – minified Quixe without Glk library is in the same ballpark, though this is a flawed comparison. But it’s not good either by web standards. Whenever I peek under the hood to see what’s taking up space in the wasm module, a huge chunk of it is for things that a JS app just gets for free from the browser: math functions, string operations, memory management, serialization (JS gets JSON for free, but a Rust JSON parser would be too large so I avoid JSON for talking to JS), raising exceptions on basic programming errors, etc.
I have tracked down the version from when I first added a script for checking the size. Back then, the “release build” wasm module was 618 KiB, which wasm-opt reduced to 501 KiB. ↩︎
158k is impressive! What are you using to discover bits you can remove? The tools you linked to, opt and strip don’t save anything for me.
When I added sound support to Parchment I had a problem: no browser supports all the audio formats in Blorb. So I made a little WASM library in Rust, stitching together two Rust audio libraries. It’s only 140 lines of code (which is more than it should’ve been, Symphonia is great at audio, but using it requires a lot of boilerplate code), and compiles to a 543kb WASM file. Perhaps it could be shrunk further, but I haven’t tried other than switching to LLVM’s file size optimisation mode. This is one of Dan’s type 2 use cases, and it’s where both WASM and Rust shine.
Twiggy has been helpful for attributing code size to function names, though it has a bunch of limitations. Also, while there have been a few low hanging fruit that could simply be removed once I noticed them, I’ve had to combine it with a fair amount of educated guesses and experimentation. A lot of cumulative savings come from repeatedly wondering “why does (necessary) part require so much code anyway?” and trying out ways to rewrite it that I’d expect to result in smaller code.
The other important knobs are various compiler (LTO + opt-level=s) and linker (--compress-relocations) flags, plus feeding the module through wasm-opt.
Thanks. I just tried -flto again and it’s working. A while back, i was getting code crashes. Perhaps a corrupt build. Anyway, this has saved quite a bit. I’m well under 2MB now. I also made a big saving with -Oz which i didn’t expect to gain much over -Os, but it did.
I have to correct myself. Transferred is 1.1MB for the first attempt. but resources were around 9MB.
This conversation has been interesting because I never really optimized my web load. And of course, this is a good idea.
I found that there are several resources I load before I actually display anything. The story file is one, but that’s usually quite small.
Turns out I should be loading the title picture asap and getting that on screen. Other stuff can happen afterwards.
So that’s what to do with resources, prioritise.