Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB

I'm trying out a simple hello world WebAssembly example and I'm having trouble understanding an error I'm seeing in Chrome 59:

RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.

src/wasm/counter.wasm:13
  10 | let wa;
  11 | const make = source => {
  12 |   // buffer should already be set
> 13 |   return wa = new Module(buffer);
  14 | };
  15 | 
  16 | const WebAssemblyModule = function(deps = {

I've followed the steps in this tutorial, and I can build everything without error. I'm using create-react-app rewired with wasm-loader.

If I'm using my local build of the counter module I get the error I mentioned in the beginning. If I try and use a pre-built version (for example the one in this project) it works fine.

When I build my module, I'm using the same command as specified in the tutorial. The project with the working module has the same command listed in its README:

emcc counter.c -O1 -o counter.wasm -s WASM=1 -s SIDE_MODULE=1

Any idea what might be causing the error?

like image 647
Alex Ciminian Avatar asked Jul 24 '17 15:07

Alex Ciminian


1 Answers

Some browsers limit the size of modules that can be compiled synchronously because that blocks the main thread. As the error message says, they'd rather have you use WebAssembly.compile which returns a promise. I'd advise you to go further and use WebAssembly.instantiate which will both compile and instantiate asynchronously and, in some cases, generate higher performance code. See its documentation, the signature is:

Promise<WebAssemblyInstantiatedSource>
  instantiate(BufferSource bytes [, importObject])

bytes is the same buffer you were passing to Module above, and importObject is the same thing you'd have passed to Instance.


Another option is to make your .wasm file smaller. That's pretty brittle because the main-thread size limit is arbitrary and you're not really in control of your generated code's size. You could try compiling with -O2 or -Os, and you can run binaryen's optimizer to try to reduce size. You could also split your code into multiple smaller modules, compile each individually, and then dynamically link them together (share import / export, and use the same memory for all of them).

But again, that's not really something you should rely on, and you're still blocking the main thread.


Yet another option is to move all your code to a WebWorker. You can block them as much as you want, no need for Promises.

like image 150
JF Bastien Avatar answered Oct 28 '22 11:10

JF Bastien