RC W5D2 - Relentlessly resourceful

WebAssembly

I ran a demo on WebAssembly at Presentations last Friday. I had to gloss over a number of details given the 5-minute format, so I did an extended version today.

As per Lin Clark's post, WebAssembly is "taking code written in programming languages other than JavaScript and running that code in the browser". Today I added how a major project underway is a standalone runtime so .wasm binaries can be run independent of the browser.

Re: portability, I previously used the following image with C, C++ and Rust as starting points. These so-called system languages are particularly suitable for compiling to WebAssembly given the absence of a garbage collector and minimal language runtime. I'm often confused by the term runtime, more detailed explanation here.

Re: performance, I had mentioned how WebAssembly gets to skip some execution steps compared to JavaScript. The wrinkle is the JIT currently doesn't know how to deal with WebAssembly directly, limiting speed gains (see 'trampolining' here). In fact, the main example I've come across in practice is a Figma post focusing on speed ups from smaller binaries.

Re: security, I had skipped this entirely. I provided a high-level overview of the ArrayBuffer today.

In the demo, I compiled and ran WebAssembly. I spoke a bit more on future improvements on the roadmap (see 'post MVP features' here), in particular access to the DOM and direct loading of WebAssembly modules (hence no need for a web server).

Microbenchmarks

Reviewing the feedback on the 5-minute presentation, comparing the performance of WebAssembly against JavaScript was at the top of the list. What's amusing is I wanted to learn WebAssembly but ended up having newfound respect for the V8 JavaScript engine.

I started with prime number generation, and puzzled how WebAssembly ran slower against JavaScript. Then I realized how even the Rust implementation ran slower against JavaScript. Andrey found a post on this exact comparison. My sense was the execution involved one main loop, which provided a textbook example for JIT optimization.

Moving on, I found a post on Julia microbenchmarks and thought I can simply use the tests where JavaScript wasn't as fast. Running matrix multiply, I had LLVM issues and discovered I needed to install Fortran to use BLAS. Oh boy. Post-installation I might still have been missing some symlinks, so kept this on hold for the time being.

With quicksort, Rust completed in half the time of JavaScript but I didn't have time to set this up in the browser before the presentation. I did have the n-queens problem as an example where Rust (compiled to WebAssembly) ran in half the time of JavaScript, in the browser.

When running microbenchmarks in the past, it's always been about comparing two algorithms in the same language. Cross-language benchmarks are fascinating. Do you replicate step-by-step, or rewrite in the way the language performs best (hence needing to know best practices in both languages)? If the latter, would there be more subtlety when comparing imperative against functional languages?

The other issue I had was microbenchmarking in the browser. If you set up the start and end times in JavaScript, does this mean you can't time the parsing stage (since by that point the code is already parsed)?

Content: 15 startups in 21 months

In his essay, Paul Graham isolated the key quality needed in a founder - relentless resourceful(ness). The story that often gets told is of Airbnb, where the co-founders managed to extend their runway by selling cereal during the 2008 Presidential Elections. The story I quite like is actually this one.

https://medium.com/@mecolalu/how-we-did-15-startups-in-21-months-a7008c8f2c97

There's a happy ending; I won't spoil it more than that.