Some lessons learnt after converting a native module to WebAssembly
Posted on May 22, 2019 • 2 minutes • 301 words
I released my first WebAssembly module here on GitHub . Here are some lessons I learnt during the process. Please don’t take it for granted. These things might be true, or not. I’m not sure. I just worked on it for the last few days.
Cache WebAssembly instance to save some time on initialization
const Module = require('yourmodule')
const mod = Module()
const resolveCache = new Map()
mod.onRuntimeInitialized = function() {
resolveCache.set(resolvePath, mod)
// mod.your_method()
}
Size of WebAssembly files matter
I accidentally publish an alpha build with iostream
imported (I was debugging in C++ with std::cout
!!!!), which result in {.js,.wasm}
files significantly bigger. Bigger files mean longer time to download and compile.
A small fix to remove #include <iostream>
increases performance of camaro (wasm) from ~200 ops/second to ~260 ops/second. Still far from the the old camaro performance (~800 ops/second) but it’s a start.
To me, WebAssembly is a huge win. The performance hit is still big but I think it’s just me doing something wrong haha. It’s my first WebAssembly module so there’s a lot to learn from here. Aside from that, camaro (wasm) is a big improvement in this version such as:
- Smaller footprint, zero dependencies.
- Closing a bunch of bug reports related to module installation on GitHub.
- Serverless (eg: AWS Lambda) friendly as compilation is no longer required. No more downloading prebuilt artifacts from GitHub as well.
I still don’t know how to return arbitrary shape object from C++ to JS land
I still don’t know how to do this. For native module, it’s easier with node-addon-api
. I’m still trying to figure this out.
This make camaro
slows down a bit because I stringify the JSON object in C++ and parse again in JavaScript (😱 horrifying, I know!)