This document summarizes Ujjwal Sharma's talk on multithreading in JavaScript. It discusses the history and need for multithreading given modern hardware, as well as past failed attempts and recent successes in standards. The talk outlines a vision for the future that improves both asynchronous and threaded concurrency models in JavaScript, including proposals for module blocks and shared disjoint heaps to improve data/code sharing and higher-level structs for concurrent access.
8. WHY MULTICORE JS? 👨💻
JavaScript was designed in 1995 (26 years ago)
CPU hardware is scaling with multi-core, big/little rather than frequency
The client side is moving to the Web
JS and WASM are taking over servers too!
e.g., Fastly's and CloudFlare's models
Important to expose hardware capabilities to software
@ryzokuken
9. WHY DO I CARE? 😳
Your users use a mobile phone
You run JS or WASM on a server
You build computationally heavy web applications
You want to utilize full hardware capabilties.
@ryzokuken
10. OLD NEWS ⏳
High-level async constructs (allows work in the background)
Workers (and SharedWorkers, ServiceWorker, AudioWorklet, etc)
postMessage
MessageChannel
async/await
WebAssembly MVP
@ryzokuken
13. ARE STANDARDS A GOOD PLACE TO GET STUFF DONE? 😅
Project Fugu shows that multi-implementer standards aren't the only way to
ship
However, the JS and Wasm world does operate on a lockstep model
Many big efforts have successfully been developed in standards bodies and
then shipped broadly
@ryzokuken
14. ARE STANDARDS A GOOD PLACE TO GET STUFF DONE? 😅
Important to have a coherent whole for JS and Wasm
JS/Wasm engine teams have historically been more conservative about
implementing non-standard things than higher levels of Chromium
When this path was not taken, it is seen as a mistake, e.g., PJS and
strong mode
@ryzokuken
24. WEB-LIKE 🕸
GOODS
BADS
Ease of reasoning + using
Causal
Data race free by construction
Isolation
Asynchronous = smoother
Less focused on manual synchronization mechanics (locks, queues, etc)
Leaving performance on the table
@ryzokuken
25. THREAD-LIKE 🧵
GOODS
BADS
WebAssembly interop
WasmGC interop
Good performance
Hard to reason & use
Manual synchronization
Data races
Acausal astonishments
"Must be this tall"
Exposes more timing channels
@ryzokuken
28. PHASE 1
WEB-LIKE
THREAD-LIKE
Language support for asynchronous communication
Ability to spawn units of computation
Shared memory
Basic synchronization primitive
Ability to spawn threads
@ryzokuken
30. PHASE 2
WEB-LIKE
THREAD-LIKE
Ergonomic and performant data transfer
Ergonomic and performant code transfer
Higher level objects that allow concurrent access
Higher level synchronization mechanisms
@ryzokuken
31. PHASE 2 🕸
Designed to address biggest observed pain points
Transferring data is expensive:
Transferrables very limited
Weird reparenting of [[Prototype]] even when transferred
Often copied
Transferring data is unergonomic:
Often requires serialization/deserialization
Identity discontinuity
Transferring code is basically not possible, we transfer strings
@ryzokuken
32. PROPOSAL: MODULE BLOCKS
Aims to solve: Ergonomic sharing of code
Spearheaded by Surma
let moduleBlock = module {
export let y = 1;
};
let moduleExports = await import(moduleBlock);
assert(moduleExports.y === 1);
assert(await import(moduleBlock) === moduleExports);
@ryzokuken
33. UPCOMING PROPOSAL: SHARED DISJOINT HEAPS
Aims to solve: Ergonomic and performant sharing of data and code
Let developers separate their heap
Agent-local heaps can point into shareable heaps
Shareable heaps cannot point into agent-local heaps
Unit of sharing is transferable heap
@ryzokuken
34. PHASE 2 🧵
Also designed to address biggest observed pain points
Nobody knows how to use SABs and Atomics well
Impedance mismatch too high
@ryzokuken
35. PROPOSAL: STRUCTS
Aims to solve: Higher-level objects that allow concurrent access
Spearheaded by Shu-yu Guo
struct class Box {
constructor(x) { this.x = x; }
x;
}
let box = new Box();
box.x = 42; // x is declared
assertThrows(() => { box.y = 8.8; }); // structs are
sealed
assertThrows(() => { box.__proto__ = {} }); // structs are
sealed
@ryzokuken