Skip to content

Instantly share code, notes, and snippets.

@frank-dspeed
Created October 8, 2022 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frank-dspeed/5d608a99cf177bb63465786826397123 to your computer and use it in GitHub Desktop.
Save frank-dspeed/5d608a99cf177bb63465786826397123 to your computer and use it in GitHub Desktop.
Create WASM Bindgen Example

To start, install Cargo/Rust and wasm-pack. Once the base installation setup is done, you’re ready to start coding.

Example string based processing in rust is save as UTF-8 is true for Stealify and Rust

pub fn greet() -> String { 
  String::from("Hello World!") 
}

Full Example: mutable pointer to an array buffer from JS memory aka sharedArrayBuffer

mod utils;

use wasm_bindgen::prelude::*;

// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen]
pub fn greet(input: &mut [u8]) -> Vec<u8> {
    input[0] = 10; // just changing some value here
    Vec::from(input)
}
wasm-pack build --target=nodejs

Output files:

pkg/<project_name>_bg.wasm
    <project_name>.js
// main.js - the main executional file to start program from
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.once('message', (message) => {
  console.log(message);
});

// worker.js - worker file to be called from main.js
const { parentPort } = require('worker_threads');
const {greet} = require('./pkg/<project_name>.js');
parentPort.once('message', (message) => {
  parentPort.postMessage(greet());
});

build an entire shared type system for WebAssembly, because everything could be represented as a plain byte array. Remember in C when you had to make memcpy(...) with pointers being an actual structure? This could be a similar scenario, but there is no specific use case yet. Usually, just a plain byte array messaging will do.

Benchmarks

10000 calls on slow machine

ffi-napi: 1103.680ms is a napi addon doing dynamic ffi calls to c
sbffi: 39.981ms is a dyncall using napi addon that passes options and data via the same sharedArrayBuffer to dyncall 
napi-addon: 8.214ms Nativ napi addon calls
napi-addon-sb: 6.795ms Nativ napi addon calls using sharedArrayBuffers for options and data
wasm: 2.802ms Uses sharedArrayBuffers out of the Box accepts memory pointers
js: 2.644ms Uses Native Objects no overhead so baseline

ffi-napi: A successor to node-ffi compatible with modern versions of Node.js. sbffi: This library. napi-addon: A very simple/normal Node.js addon using NAPI in C. napi-addon-sb: A NAPI addon using the same shared-buffer technique as sbffi, but with a hard-coded function call, rather than a dynamic/FFI call. wasm: The adding function compiled to WebAssembly. js: Re-implementing the function in plain JavaScript.

https://medium.com/doctolib/calling-into-thread-unsafe-dlls-with-node-ffi-1ef83806a50c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment