WebAssembly Threads Arrive in Chrome 70 with Origin Trial

Chrome 70 now ships support for WebAssembly threads under an origin trial. This brings a core primitive from native application development—parallel computation via threads—to compiled C and C++ code running on the web. For developers familiar with pthreads, the standardized POSIX threading API, the capability means existing threaded code can now be recompiled to Wasm and run in true multi-threaded mode inside the browser.

The feature is part of ongoing work by the WebAssembly Community Group. V8 has implemented the necessary engine-level support, exposed through Chrome's origin-trial mechanism. This lets developers experiment with the feature before full standardization, providing real-world feedback that will shape its final form.

Workers vs. Wasm Threads

Browser-side parallelism via Web Workers has existed for years, but workers do not share mutable state—they communicate by message-passing, and each runs in its own V8 isolate with no shared compiled code or JavaScript objects. Wasm threads are different: they share the same Wasm memory, implemented at the JavaScript level with a SharedArrayBuffer. Each Wasm thread runs inside a Web Worker, but the shared underlying memory lets them operate on the same data simultaneously, much as they would natively.

That shared-memory model comes with the same responsibilities as in any traditional threaded application: code must manage access to the shared memory itself. C and C++ libraries that use pthreads can therefore be compiled to Wasm and run in this environment, letting hardware cores work together on shared data.

A Minimal Threaded C Example

A simple C program demonstrates the pattern. The main() function declares a fg_val and a bg_val, then uses pthread_create() to spin up a background thread that computes a fibonacci sequence value for bg_val. The foreground thread—running the remainder of main()—computes the value for fg_val at the same time. Once the background thread finishes, both results print out.

#include <pthread.h>
#include <stdio.h>

// Calculate Fibonacci numbers shared function
int fibonacci(int iterations) {
    int     val = 1;
    int     last = 0;

    if (iterations == 0) {
        return 0;
    }
    for (int i = 1; i < iterations; i++) {
        int     seq;

        seq = val + last;
        last = val;
        val = seq;
    }
    return val;
}
// Start function for the background thread
void *bg_func(void *arg) {
    int     *iter = (void *)arg;

    *iter = fibonacci(*iter);
    return arg;
}
// Foreground thread and main entry point
int main(int argc, char *argv[]) {
    int         fg_val = 54;
    int         bg_val = 42;
    pthread_t   bg_thread;

    // Create the background thread
    if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
        perror("Thread create failed");
        return 1;
    }
    // Calculate on the foreground thread
    fg_val = fibonacci(fg_val);
    // Wait for background thread to finish
    if (pthread_join(bg_thread, NULL)) {
        perror("Thread join failed");
        return 2;
    }
    // Show the result from background and foreground threads
    printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val);

    return 0;
}

Compiling with Thread Support

To build the example for the browser, the first step is an Emscripten SDK install, ideally version 1.38.11 or later. The emcc compile command then takes two extra flags:

emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c

The -s USE_PTHREADS=1 flag turns on threading for the compiled module, and -s PTHREAD_POOL_SIZE=2 tells the compiler to generate a pool of two threads. At runtime, the module loads, Web Workers are created for each pool entry, the module is shared with each worker, and those workers are used whenever pthread_create() is called. Each worker instantiates the module against the same memory, so they can cooperate on shared data.

Ballancing the pool size is important: too small, and pthread_create() fails once the pool is exhausted; too large, and the browser creates Web Workers that sit idle consuming memory. The pool size should match the maximum number of threads the application expects to need.

Worth noting for scaling: V8's changes in version 7.0 share compiled native code for Wasm modules passed between workers. This applies even to very large applications that need many workers, since the compiled artifact does not have to be rebuilt for each.

Enabling and Running

The fastest path to testing is flipping the feature flag. In Chrome 70 or later, navigate to about://flags, locate the experimental WebAssembly threads setting, change it to Enabled, and restart the browser.

Once enabled, a minimal HTML page is enough to load and execute the threaded module:

<!DOCTYPE html>
<html>
  <title>Threads test</title>
  <body>
    <script src="test.js"></script>
  </body>
</html>

Serving that page from a basic web server and opening it shows the program's output in the DevTools console, confirming the threaded execution completed successfully. Developers are encouraged to apply the same steps to their own threaded code.

Going Beyond Local Flags: Origin Trials

Experimental flags serve development purposes, but testing with real users requires an origin trial. This approach provisions a testing token bound to the developer's domain. With that token deployed, the feature works for users on supporting browsers, such as Chrome 70 and onward. Tokens are applied for via the origin-trial registration form.

Working hosted examples also demonstrate the capability without requiring a local build—one basic threaded module, and another showing four threads collaborating on ASCII art output.

Soliciting Feedback

The arrival of Wasm threads makes it feasible to port C and C++ applications and libraries requiring pthreads support to the web. Implementation feedback from developers working with the feature helps validate its usefulness and inform the standardization process. Developers can report issues or participate in the discussion within the WebAssembly Community Group threads repository.