Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development-use jco serve

jco serve is a convenient development utility for running Preview 2 HTTP components (in particular components that export the wasi:http/incoming-handler interface) in Node.js.

Warning

jco serve is intended for development and testing only.

It is not production ready, and these benchmarks should not be interpreted as production deployment guidance.

jco serve does not yet support Preview 3 HTTP components.

Caveats

Given the “for development” development nature of jco serve, this benchmark measures Jco’s Node.js development server, not the general performance of Preview 2 HTTP components.

A production deployment would typically use Wasmtime or another production-oriented component runtime, which is substantially more efficient than jco serve.

Performance depends on the component, generated bindings, JavaScript runtime, hardware, and workload. Measurements from one application or machine should not be treated as production capacity estimates. Use this benchmark to compare development-server configurations rather than to estimate production capacity.

Request isolation

By default, jco serve reuses a single instantiated component across requests.

The --isolate-requests=instance argument introduces a light (and permeable) layer of isolation: a fresh component instance while retaining the same JavaScript isolate and module cache.

The stronger --isolate-requests=worker mode creates a worker thread with a separate V8 isolate and module cache for every request.

Note

The --isolate-requests option selects worker isolation by default

Worker mode efficiency

Workers are one-shot: each handles exactly one request and is then terminated and replaced, so prewarming does not reuse JavaScript globals or module caches across requests.

As the cost of isolated workers is quite high, Worker mode maintains a pool of 50 prewarmed workers by default.

The capacity can be adjusted with --isolate-worker-pool-size. Larger pools can hide worker startup latency during bursts, at the cost of higher server startup time and memory use.

Running the benchmark

Jco includes an opt-in end-to-end benchmark that compares both isolation modes with a shared component and a native Node.js HTTP handler:

pnpm --filter @bytecodealliance/jco bench:serve-isolation

Note

The benchmark is not part of the normal test suite.

The serve-isolation benchmark suite builds a minimal HTTP component, starts a real NodeJS server for each mode, and makes sequential requests to expose per-request overhead. It reports requests per second and mean, median, and p95 latency.

By default, each mode receives 100 warmup requests followed by 10,000 measured requests.

Worker isolation intentionally creates a worker for every request, so a complete default run can take a long time.

Based on the reference result below, benchmarking all three worker pool sizes may take a while. A smaller smoke run can be requested before committing to the full benchmark:

JCO_SERVE_BENCH_WARMUP=5 \
JCO_SERVE_BENCH_REQUESTS=30 \
pnpm --filter @bytecodealliance/jco bench:serve-isolation

The reference result recorded below can be reproduced with its original sample sizes:

JCO_SERVE_BENCH_WARMUP=10 \
JCO_SERVE_BENCH_REQUESTS=100 \
pnpm --filter @bytecodealliance/jco bench:serve-isolation

Componentization is deliberately excluded from the timed measurements. Because building the fixture can still make repeated benchmark runs inconvenient, the generated component can be retained and reused:

JCO_SERVE_BENCH_COMPONENT_OUT=/tmp/jco-serve-benchmark.wasm \
pnpm --filter @bytecodealliance/jco bench:serve-isolation

JCO_SERVE_BENCH_COMPONENT=/tmp/jco-serve-benchmark.wasm \
pnpm --filter @bytecodealliance/jco bench:serve-isolation

Reference result

Using Node.js 24.19.0 on a 6-vCPU Intel Xeon 2.60 GHz virtual machine, the benchmark made 10 warmup requests followed by 100 measured sequential requests per mode:

ModeRequests/sMean latencyMedian latencyp95 latency
Native node:http598.131.67 ms1.69 ms2.03 ms
Shared component225.074.44 ms4.31 ms5.40 ms
Instance isolation22.8843.71 ms43.24 ms47.59 ms
Worker, pool size 14.15240.95 ms239.36 ms274.28 ms
Worker, pool size 5013.5573.82 ms70.14 ms100.00 ms
Worker, pool size 10014.7867.66 ms65.14 ms95.25 ms

Note

The performance ratios here are likely more improtant than the absoltue numbers.

This result illustrates the relative cost of the isolation mechanisms for a minimal component.

A larger component, concurrent traffic, different response sizes, pool utilization, or another Node.js version can change both the absolute results and the ratios between modes.