Using Workers (Threads)
QuickJS supports worker threads through theos.Worker API in quickjs-libc, enabling multi-threaded JavaScript execution with message passing between workers.
Worker support requires building with thread support (default when pthreads is available).
Worker Basics
Creating Workers
Workers run JavaScript in separate threads with isolated memory:Worker Script
worker.js:
Memory Isolation
Each worker has its own:- JSRuntime - Separate heap and garbage collector
- JSContext - Isolated global object
- Memory limit - Independent from parent
Message Passing
Structured Clone
Messages are serialized/deserialized (structured clone algorithm):SharedArrayBuffer
For true shared memory, use SharedArrayBuffer:C API for Workers
Custom Runtime Factory
Override worker runtime creation:quickjs-libc.h):
Custom Context Factory
Worker Lifecycle
Creating Workers
Terminating Workers
Thread Safety
Runtime Isolation
Each worker has its own runtime - no shared runtime between threads:Stack Top Updates
If moving a runtime between threads:Atomic Operations
UseAtomics for SharedArrayBuffer synchronization:
Thread Sanitizer
During development, use ThreadSanitizer to catch race conditions:TSan will report data races if you accidentally share memory incorrectly.
Worker Pool Pattern
Debugging Workers
Enable Debug Output
Worker Errors
Best Practices
- Keep workers simple - One worker per task type
- Avoid creating too many workers - Typically 1-2x CPU core count
- Use SharedArrayBuffer sparingly - Message passing is safer
- Handle worker errors gracefully - Workers can crash independently
- Set memory limits - Prevent one worker from consuming all memory
- Profile carefully - Workers add overhead; ensure they’re worth it
- Test with TSan - Catch threading bugs early
Limitations
- Workers cannot share JSContext or JSRuntime
- No DOM or browser-specific APIs
- Message serialization has overhead
- Worker creation has startup cost
- No built-in worker pool - implement your own
Related C API Functions
Functions used internally by worker implementation (fromquickjs.h):
Next Steps
- Memory Management - Configure per-worker memory
- Performance - Optimize worker throughput
- Embedding - Integrate workers in embedded apps