Node.js
This page summarizes Node.js benchmark runs for Knitting on node 24.12.0 (arm64-darwin).
IPC (Node)
Section titled “IPC (Node)”This benchmark compares one round-trip between a main thread and workers using different transports. Knitting has the lowest overhead in this setup:
1message: Knitting is about6xfaster than workerpostMessage,15xfaster than websocket, and57xfaster than HTTP.25messages: Knitting is about4xfaster than workerpostMessage.50messages: Knitting is about3.5xfaster than workerpostMessage.
clk: ~3.67 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • knitting | avg | min | p75 | p99 | max || --------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || 1 thread → (1) | ` 2.22 µs/iter` | ` 1.12 µs` | ` 2.63 µs` | ` 5.54 µs` | ` 1.27 ms` || 1 thread → (25) | ` 15.99 µs/iter` | ` 14.33 µs` | ` 16.56 µs` | ` 17.15 µs` | ` 19.87 µs` || 1 thread → (50) | ` 30.67 µs/iter` | ` 28.07 µs` | ` 31.19 µs` | ` 32.16 µs` | ` 33.21 µs` |clk: ~3.71 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • websocket | avg | min | p75 | p99 | max || ------------ | ---------------- | ----------- | ----------- | ----------- | ----------- || local → (1) | ` 26.83 µs/iter` | ` 12.83 µs` | ` 26.96 µs` | ` 85.25 µs` | `468.58 µs` || local → (25) | `183.39 µs/iter` | `130.33 µs` | `195.83 µs` | `272.71 µs` | `976.96 µs` || local → (50) | `345.79 µs/iter` | `252.42 µs` | `363.46 µs` | `456.25 µs` | ` 1.45 ms` |clk: ~3.70 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • worker | avg | min | p75 | p99 | max || ------------------ | ---------------- | ----------- | ----------- | ----------- | ----------- || postMessage → (1) | ` 11.49 µs/iter` | ` 7.29 µs` | ` 12.00 µs` | ` 33.21 µs` | `344.50 µs` || postMessage → (25) | ` 56.73 µs/iter` | ` 55.91 µs` | ` 56.83 µs` | ` 57.24 µs` | ` 57.76 µs` || postMessage → (50) | `102.10 µs/iter` | ` 68.83 µs` | `105.63 µs` | `221.17 µs` | ` 3.49 ms` |clk: ~3.68 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • http | avg | min | p75 | p99 | max || ------------ | ---------------- | ----------- | ----------- | ----------- | ----------- || local → (1) | ` 65.42 µs/iter` | ` 38.42 µs` | ` 66.13 µs` | `174.38 µs` | `601.33 µs` || local → (25) | `966.49 µs/iter` | `859.96 µs` | ` 1.01 ms` | ` 1.22 ms` | ` 2.04 ms` || local → (50) | ` 1.90 ms/iter` | ` 1.71 ms` | ` 1.99 ms` | ` 2.17 ms` | ` 2.64 ms` |Knitting vs Worker (Node)
Section titled “Knitting vs Worker (Node)”These charts compare the same payload families sent through Knitting and worker_threads.
One message
Section titled “One message”With a single value per call, Knitting is consistently faster:
- For small primitives, Knitting is roughly
10-14xfaster than workerpostMessage. - Worker
postMessagestays near~10 µs/itereven for tiny payloads. - For larger payloads, Knitting still holds around a
4xadvantage (for example, big object:4.15 µsvs15.74 µs).
clk: ~3.71 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • knitting 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (1) | ` 1.19 µs/iter` | `500.00 ns` | ` 1.54 µs` | ` 2.88 µs` | ` 1.33 ms` || bigint small -> (1) | ` 1.05 µs/iter` | `551.27 ns` | ` 1.39 µs` | ` 1.65 µs` | ` 1.67 µs` || bigint large -> (1) | ` 2.36 µs/iter` | ` 1.29 µs` | ` 2.54 µs` | ` 5.83 µs` | ` 1.24 ms` || boolean true -> (1) | ` 1.10 µs/iter` | `534.90 ns` | ` 1.46 µs` | ` 1.59 µs` | ` 1.61 µs` || boolean false -> (1) | ` 1.06 µs/iter` | `531.85 ns` | ` 1.49 µs` | ` 1.61 µs` | ` 1.62 µs` || undefined -> (1) | ` 1.05 µs/iter` | `531.94 ns` | ` 1.44 µs` | ` 1.60 µs` | ` 1.65 µs` || null -> (1) | ` 1.03 µs/iter` | `534.34 ns` | ` 1.35 µs` | ` 1.67 µs` | ` 1.90 µs` || string -> (1) | ` 1.57 µs/iter` | `583.00 ns` | ` 2.13 µs` | ` 3.29 µs` | ` 1.26 ms` || json object -> (1) | ` 3.64 µs/iter` | ` 2.50 µs` | ` 3.75 µs` | ` 8.67 µs` | ` 1.27 ms` || json array -> (1) | ` 4.73 µs/iter` | ` 4.28 µs` | ` 4.90 µs` | ` 5.21 µs` | ` 5.22 µs` || Uint8Array -> (1) | ` 3.11 µs/iter` | ` 1.17 µs` | ` 3.83 µs` | ` 8.08 µs` | ` 1.25 ms` || ArrayBuffer -> (1) | ` 3.24 µs/iter` | ` 1.50 µs` | ` 4.21 µs` | ` 8.50 µs` | ` 1.27 ms` || Buffer -> (1) | ` 2.87 µs/iter` | ` 1.17 µs` | ` 3.83 µs` | ` 7.25 µs` | ` 1.24 ms` || string huge -> (1) | ` 3.73 µs/iter` | ` 2.00 µs` | ` 4.38 µs` | ` 8.75 µs` | ` 1.25 ms` || Int32Array -> (1) | ` 2.84 µs/iter` | ` 1.80 µs` | ` 3.32 µs` | ` 3.78 µs` | ` 3.86 µs` || Float64Array -> (1) | ` 3.37 µs/iter` | ` 1.46 µs` | ` 4.17 µs` | ` 8.79 µs` | ` 1.27 ms` || BigInt64Array -> (1) | ` 2.70 µs/iter` | ` 1.77 µs` | ` 3.19 µs` | ` 3.69 µs` | ` 3.87 µs` || BigUint64Array -> (1) | ` 3.03 µs/iter` | ` 1.21 µs` | ` 3.83 µs` | ` 7.58 µs` | ` 1.26 ms` || DataView -> (1) | ` 2.89 µs/iter` | ` 1.87 µs` | ` 3.37 µs` | ` 3.77 µs` | ` 3.85 µs` || Date -> (1) | ` 1.34 µs/iter` | `542.00 ns` | ` 1.63 µs` | ` 2.71 µs` | ` 1.24 ms` |
| • knitting 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (100) | ` 27.35 µs/iter` | ` 15.42 µs` | ` 33.79 µs` | ` 60.38 µs` | `222.08 µs` || bigint small -> (100) | ` 26.77 µs/iter` | ` 24.24 µs` | ` 28.06 µs` | ` 28.61 µs` | ` 31.03 µs` || bigint large -> (100) | ` 72.11 µs/iter` | ` 53.50 µs` | ` 73.83 µs` | `137.13 µs` | ` 1.35 ms` || boolean true -> (100) | ` 28.12 µs/iter` | ` 25.30 µs` | ` 29.23 µs` | ` 31.10 µs` | ` 35.62 µs` || boolean false -> (100) | ` 27.33 µs/iter` | ` 20.98 µs` | ` 29.51 µs` | ` 29.70 µs` | ` 32.56 µs` || undefined -> (100) | ` 29.03 µs/iter` | ` 22.39 µs` | ` 31.83 µs` | ` 32.06 µs` | ` 32.95 µs` || null -> (100) | ` 28.28 µs/iter` | ` 25.01 µs` | ` 29.89 µs` | ` 30.11 µs` | ` 30.44 µs` || string -> (100) | ` 37.10 µs/iter` | ` 33.71 µs` | ` 38.45 µs` | ` 39.78 µs` | ` 40.58 µs` || json object -> (100) | `125.75 µs/iter` | `106.08 µs` | `128.67 µs` | `216.33 µs` | ` 1.42 ms` || json array -> (100) | `178.12 µs/iter` | `154.33 µs` | `183.25 µs` | `290.88 µs` | ` 1.55 ms` || Uint8Array -> (100) | `108.89 µs/iter` | ` 54.00 µs` | `137.63 µs` | `209.29 µs` | ` 2.93 ms` || ArrayBuffer -> (100) | `119.46 µs/iter` | ` 63.50 µs` | `145.71 µs` | `222.29 µs` | ` 2.59 ms` || Buffer -> (100) | `103.74 µs/iter` | ` 54.42 µs` | `143.88 µs` | `207.08 µs` | ` 2.88 ms` || string huge -> (100) | `167.81 µs/iter` | `111.54 µs` | `208.21 µs` | `265.50 µs` | ` 1.44 ms` || Int32Array -> (100) | `116.92 µs/iter` | ` 55.12 µs` | `143.83 µs` | `214.25 µs` | ` 3.00 ms` || Float64Array -> (100) | `120.60 µs/iter` | ` 61.96 µs` | `139.67 µs` | `224.54 µs` | ` 2.08 ms` || BigInt64Array -> (100) | `107.85 µs/iter` | `102.95 µs` | `109.66 µs` | `111.51 µs` | `113.46 µs` || BigUint64Array -> (100) | `112.46 µs/iter` | ` 56.50 µs` | `139.96 µs` | `207.25 µs` | ` 3.15 ms` || DataView -> (100) | `109.26 µs/iter` | ` 59.25 µs` | `140.21 µs` | `214.38 µs` | ` 3.14 ms` || Date -> (100) | ` 33.41 µs/iter` | ` 31.27 µs` | ` 33.97 µs` | ` 35.82 µs` | ` 36.27 µs` |
| • worker 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (1) | ` 11.13 µs/iter` | ` 11.09 µs` | ` 11.15 µs` | ` 11.18 µs` | ` 11.19 µs` || bigint small -> (1) | ` 11.09 µs/iter` | ` 10.99 µs` | ` 11.11 µs` | ` 11.13 µs` | ` 11.15 µs` || bigint large -> (1) | ` 11.06 µs/iter` | ` 10.99 µs` | ` 11.07 µs` | ` 11.10 µs` | ` 11.12 µs` || boolean true -> (1) | ` 11.09 µs/iter` | ` 11.02 µs` | ` 11.11 µs` | ` 11.14 µs` | ` 11.18 µs` || boolean false -> (1) | ` 11.07 µs/iter` | ` 11.02 µs` | ` 11.10 µs` | ` 11.10 µs` | ` 11.11 µs` || undefined -> (1) | ` 11.05 µs/iter` | ` 11.03 µs` | ` 11.05 µs` | ` 11.07 µs` | ` 11.09 µs` || null -> (1) | ` 11.09 µs/iter` | ` 11.03 µs` | ` 11.11 µs` | ` 11.13 µs` | ` 11.13 µs` || string -> (1) | ` 11.09 µs/iter` | ` 11.04 µs` | ` 11.12 µs` | ` 11.13 µs` | ` 11.15 µs` || json object -> (1) | ` 14.88 µs/iter` | ` 14.63 µs` | ` 14.86 µs` | ` 14.93 µs` | ` 15.82 µs` || json array -> (1) | ` 18.70 µs/iter` | ` 18.45 µs` | ` 18.65 µs` | ` 18.79 µs` | ` 19.73 µs` || Uint8Array -> (1) | ` 12.09 µs/iter` | ` 11.91 µs` | ` 12.13 µs` | ` 12.19 µs` | ` 12.35 µs` || ArrayBuffer -> (1) | ` 11.85 µs/iter` | ` 11.67 µs` | ` 11.90 µs` | ` 12.00 µs` | ` 12.10 µs` || Buffer -> (1) | ` 14.02 µs/iter` | ` 13.70 µs` | ` 14.18 µs` | ` 14.21 µs` | ` 14.29 µs` || string huge -> (1) | ` 11.23 µs/iter` | ` 11.17 µs` | ` 11.27 µs` | ` 11.34 µs` | ` 11.34 µs` || Int32Array -> (1) | ` 12.08 µs/iter` | ` 11.94 µs` | ` 12.11 µs` | ` 12.31 µs` | ` 12.34 µs` || Float64Array -> (1) | ` 12.12 µs/iter` | ` 11.99 µs` | ` 12.21 µs` | ` 12.25 µs` | ` 12.30 µs` || BigInt64Array -> (1) | ` 12.11 µs/iter` | ` 11.91 µs` | ` 12.17 µs` | ` 12.33 µs` | ` 12.41 µs` || BigUint64Array -> (1) | ` 12.10 µs/iter` | ` 11.95 µs` | ` 12.18 µs` | ` 12.23 µs` | ` 12.29 µs` || DataView -> (1) | ` 12.67 µs/iter` | ` 12.02 µs` | ` 13.01 µs` | ` 13.15 µs` | ` 13.17 µs` || Date -> (1) | ` 11.41 µs/iter` | ` 5.92 µs` | ` 12.00 µs` | ` 32.67 µs` | `168.46 µs` |
| • worker 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (100) | `173.42 µs/iter` | `121.71 µs` | `177.04 µs` | `333.04 µs` | ` 3.54 ms` || bigint small -> (100) | `178.73 µs/iter` | `122.33 µs` | `183.04 µs` | `333.79 µs` | ` 3.50 ms` || bigint large -> (100) | `171.77 µs/iter` | `123.63 µs` | `175.42 µs` | `325.08 µs` | ` 3.16 ms` || boolean true -> (100) | `168.30 µs/iter` | `119.96 µs` | `172.38 µs` | `321.25 µs` | ` 3.08 ms` || boolean false -> (100) | `168.24 µs/iter` | `119.42 µs` | `171.92 µs` | `327.38 µs` | ` 3.18 ms` || undefined -> (100) | `174.87 µs/iter` | `122.58 µs` | `180.38 µs` | `324.38 µs` | ` 3.31 ms` || null -> (100) | `177.45 µs/iter` | `122.75 µs` | `183.29 µs` | `318.17 µs` | ` 3.12 ms` || string -> (100) | `172.13 µs/iter` | `121.83 µs` | `175.33 µs` | `311.46 µs` | ` 3.44 ms` || json object -> (100) | `349.71 µs/iter` | `272.13 µs` | `358.25 µs` | `539.25 µs` | ` 3.52 ms` || json array -> (100) | `518.73 µs/iter` | `409.38 µs` | `542.92 µs` | `754.54 µs` | ` 3.59 ms` || Uint8Array -> (100) | `242.72 µs/iter` | `171.54 µs` | `253.50 µs` | `506.21 µs` | ` 2.42 ms` || ArrayBuffer -> (100) | `229.70 µs/iter` | `160.50 µs` | `239.67 µs` | `470.63 µs` | ` 2.41 ms` || Buffer -> (100) | `354.02 µs/iter` | `222.83 µs` | `376.63 µs` | `974.71 µs` | ` 1.47 ms` || string huge -> (100) | `197.79 µs/iter` | `141.29 µs` | `197.08 µs` | `371.71 µs` | ` 2.56 ms` || Int32Array -> (100) | `243.54 µs/iter` | `169.13 µs` | `254.42 µs` | `512.29 µs` | ` 2.56 ms` || Float64Array -> (100) | `243.76 µs/iter` | `170.29 µs` | `254.00 µs` | `541.63 µs` | ` 2.44 ms` || BigInt64Array -> (100) | `242.08 µs/iter` | `170.46 µs` | `252.08 µs` | `527.83 µs` | ` 2.48 ms` || BigUint64Array -> (100) | `241.30 µs/iter` | `168.63 µs` | `253.17 µs` | `481.75 µs` | ` 2.53 ms` || DataView -> (100) | `240.07 µs/iter` | `169.00 µs` | `250.58 µs` | `529.42 µs` | ` 2.49 ms` || Date -> (100) | `174.26 µs/iter` | `124.38 µs` | `178.88 µs` | `325.83 µs` | ` 3.36 ms` |100 messages
Section titled “100 messages”At 100 messages per iteration, the gap remains strong:
- Typical primitives stay around
~6-8xfaster with Knitting. - Heavier payloads still keep a clear edge at roughly
~2.4-4.2xfaster. - Batching improves throughput for both, but Knitting remains lower-overhead across payload classes.
clk: ~3.71 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • knitting 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (1) | ` 1.19 µs/iter` | `500.00 ns` | ` 1.54 µs` | ` 2.88 µs` | ` 1.33 ms` || bigint small -> (1) | ` 1.05 µs/iter` | `551.27 ns` | ` 1.39 µs` | ` 1.65 µs` | ` 1.67 µs` || bigint large -> (1) | ` 2.36 µs/iter` | ` 1.29 µs` | ` 2.54 µs` | ` 5.83 µs` | ` 1.24 ms` || boolean true -> (1) | ` 1.10 µs/iter` | `534.90 ns` | ` 1.46 µs` | ` 1.59 µs` | ` 1.61 µs` || boolean false -> (1) | ` 1.06 µs/iter` | `531.85 ns` | ` 1.49 µs` | ` 1.61 µs` | ` 1.62 µs` || undefined -> (1) | ` 1.05 µs/iter` | `531.94 ns` | ` 1.44 µs` | ` 1.60 µs` | ` 1.65 µs` || null -> (1) | ` 1.03 µs/iter` | `534.34 ns` | ` 1.35 µs` | ` 1.67 µs` | ` 1.90 µs` || string -> (1) | ` 1.57 µs/iter` | `583.00 ns` | ` 2.13 µs` | ` 3.29 µs` | ` 1.26 ms` || json object -> (1) | ` 3.64 µs/iter` | ` 2.50 µs` | ` 3.75 µs` | ` 8.67 µs` | ` 1.27 ms` || json array -> (1) | ` 4.73 µs/iter` | ` 4.28 µs` | ` 4.90 µs` | ` 5.21 µs` | ` 5.22 µs` || Uint8Array -> (1) | ` 3.11 µs/iter` | ` 1.17 µs` | ` 3.83 µs` | ` 8.08 µs` | ` 1.25 ms` || ArrayBuffer -> (1) | ` 3.24 µs/iter` | ` 1.50 µs` | ` 4.21 µs` | ` 8.50 µs` | ` 1.27 ms` || Buffer -> (1) | ` 2.87 µs/iter` | ` 1.17 µs` | ` 3.83 µs` | ` 7.25 µs` | ` 1.24 ms` || string huge -> (1) | ` 3.73 µs/iter` | ` 2.00 µs` | ` 4.38 µs` | ` 8.75 µs` | ` 1.25 ms` || Int32Array -> (1) | ` 2.84 µs/iter` | ` 1.80 µs` | ` 3.32 µs` | ` 3.78 µs` | ` 3.86 µs` || Float64Array -> (1) | ` 3.37 µs/iter` | ` 1.46 µs` | ` 4.17 µs` | ` 8.79 µs` | ` 1.27 ms` || BigInt64Array -> (1) | ` 2.70 µs/iter` | ` 1.77 µs` | ` 3.19 µs` | ` 3.69 µs` | ` 3.87 µs` || BigUint64Array -> (1) | ` 3.03 µs/iter` | ` 1.21 µs` | ` 3.83 µs` | ` 7.58 µs` | ` 1.26 ms` || DataView -> (1) | ` 2.89 µs/iter` | ` 1.87 µs` | ` 3.37 µs` | ` 3.77 µs` | ` 3.85 µs` || Date -> (1) | ` 1.34 µs/iter` | `542.00 ns` | ` 1.63 µs` | ` 2.71 µs` | ` 1.24 ms` |
| • knitting 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (100) | ` 27.35 µs/iter` | ` 15.42 µs` | ` 33.79 µs` | ` 60.38 µs` | `222.08 µs` || bigint small -> (100) | ` 26.77 µs/iter` | ` 24.24 µs` | ` 28.06 µs` | ` 28.61 µs` | ` 31.03 µs` || bigint large -> (100) | ` 72.11 µs/iter` | ` 53.50 µs` | ` 73.83 µs` | `137.13 µs` | ` 1.35 ms` || boolean true -> (100) | ` 28.12 µs/iter` | ` 25.30 µs` | ` 29.23 µs` | ` 31.10 µs` | ` 35.62 µs` || boolean false -> (100) | ` 27.33 µs/iter` | ` 20.98 µs` | ` 29.51 µs` | ` 29.70 µs` | ` 32.56 µs` || undefined -> (100) | ` 29.03 µs/iter` | ` 22.39 µs` | ` 31.83 µs` | ` 32.06 µs` | ` 32.95 µs` || null -> (100) | ` 28.28 µs/iter` | ` 25.01 µs` | ` 29.89 µs` | ` 30.11 µs` | ` 30.44 µs` || string -> (100) | ` 37.10 µs/iter` | ` 33.71 µs` | ` 38.45 µs` | ` 39.78 µs` | ` 40.58 µs` || json object -> (100) | `125.75 µs/iter` | `106.08 µs` | `128.67 µs` | `216.33 µs` | ` 1.42 ms` || json array -> (100) | `178.12 µs/iter` | `154.33 µs` | `183.25 µs` | `290.88 µs` | ` 1.55 ms` || Uint8Array -> (100) | `108.89 µs/iter` | ` 54.00 µs` | `137.63 µs` | `209.29 µs` | ` 2.93 ms` || ArrayBuffer -> (100) | `119.46 µs/iter` | ` 63.50 µs` | `145.71 µs` | `222.29 µs` | ` 2.59 ms` || Buffer -> (100) | `103.74 µs/iter` | ` 54.42 µs` | `143.88 µs` | `207.08 µs` | ` 2.88 ms` || string huge -> (100) | `167.81 µs/iter` | `111.54 µs` | `208.21 µs` | `265.50 µs` | ` 1.44 ms` || Int32Array -> (100) | `116.92 µs/iter` | ` 55.12 µs` | `143.83 µs` | `214.25 µs` | ` 3.00 ms` || Float64Array -> (100) | `120.60 µs/iter` | ` 61.96 µs` | `139.67 µs` | `224.54 µs` | ` 2.08 ms` || BigInt64Array -> (100) | `107.85 µs/iter` | `102.95 µs` | `109.66 µs` | `111.51 µs` | `113.46 µs` || BigUint64Array -> (100) | `112.46 µs/iter` | ` 56.50 µs` | `139.96 µs` | `207.25 µs` | ` 3.15 ms` || DataView -> (100) | `109.26 µs/iter` | ` 59.25 µs` | `140.21 µs` | `214.38 µs` | ` 3.14 ms` || Date -> (100) | ` 33.41 µs/iter` | ` 31.27 µs` | ` 33.97 µs` | ` 35.82 µs` | ` 36.27 µs` |
| • worker 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (1) | ` 11.13 µs/iter` | ` 11.09 µs` | ` 11.15 µs` | ` 11.18 µs` | ` 11.19 µs` || bigint small -> (1) | ` 11.09 µs/iter` | ` 10.99 µs` | ` 11.11 µs` | ` 11.13 µs` | ` 11.15 µs` || bigint large -> (1) | ` 11.06 µs/iter` | ` 10.99 µs` | ` 11.07 µs` | ` 11.10 µs` | ` 11.12 µs` || boolean true -> (1) | ` 11.09 µs/iter` | ` 11.02 µs` | ` 11.11 µs` | ` 11.14 µs` | ` 11.18 µs` || boolean false -> (1) | ` 11.07 µs/iter` | ` 11.02 µs` | ` 11.10 µs` | ` 11.10 µs` | ` 11.11 µs` || undefined -> (1) | ` 11.05 µs/iter` | ` 11.03 µs` | ` 11.05 µs` | ` 11.07 µs` | ` 11.09 µs` || null -> (1) | ` 11.09 µs/iter` | ` 11.03 µs` | ` 11.11 µs` | ` 11.13 µs` | ` 11.13 µs` || string -> (1) | ` 11.09 µs/iter` | ` 11.04 µs` | ` 11.12 µs` | ` 11.13 µs` | ` 11.15 µs` || json object -> (1) | ` 14.88 µs/iter` | ` 14.63 µs` | ` 14.86 µs` | ` 14.93 µs` | ` 15.82 µs` || json array -> (1) | ` 18.70 µs/iter` | ` 18.45 µs` | ` 18.65 µs` | ` 18.79 µs` | ` 19.73 µs` || Uint8Array -> (1) | ` 12.09 µs/iter` | ` 11.91 µs` | ` 12.13 µs` | ` 12.19 µs` | ` 12.35 µs` || ArrayBuffer -> (1) | ` 11.85 µs/iter` | ` 11.67 µs` | ` 11.90 µs` | ` 12.00 µs` | ` 12.10 µs` || Buffer -> (1) | ` 14.02 µs/iter` | ` 13.70 µs` | ` 14.18 µs` | ` 14.21 µs` | ` 14.29 µs` || string huge -> (1) | ` 11.23 µs/iter` | ` 11.17 µs` | ` 11.27 µs` | ` 11.34 µs` | ` 11.34 µs` || Int32Array -> (1) | ` 12.08 µs/iter` | ` 11.94 µs` | ` 12.11 µs` | ` 12.31 µs` | ` 12.34 µs` || Float64Array -> (1) | ` 12.12 µs/iter` | ` 11.99 µs` | ` 12.21 µs` | ` 12.25 µs` | ` 12.30 µs` || BigInt64Array -> (1) | ` 12.11 µs/iter` | ` 11.91 µs` | ` 12.17 µs` | ` 12.33 µs` | ` 12.41 µs` || BigUint64Array -> (1) | ` 12.10 µs/iter` | ` 11.95 µs` | ` 12.18 µs` | ` 12.23 µs` | ` 12.29 µs` || DataView -> (1) | ` 12.67 µs/iter` | ` 12.02 µs` | ` 13.01 µs` | ` 13.15 µs` | ` 13.17 µs` || Date -> (1) | ` 11.41 µs/iter` | ` 5.92 µs` | ` 12.00 µs` | ` 32.67 µs` | `168.46 µs` |
| • worker 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (100) | `173.42 µs/iter` | `121.71 µs` | `177.04 µs` | `333.04 µs` | ` 3.54 ms` || bigint small -> (100) | `178.73 µs/iter` | `122.33 µs` | `183.04 µs` | `333.79 µs` | ` 3.50 ms` || bigint large -> (100) | `171.77 µs/iter` | `123.63 µs` | `175.42 µs` | `325.08 µs` | ` 3.16 ms` || boolean true -> (100) | `168.30 µs/iter` | `119.96 µs` | `172.38 µs` | `321.25 µs` | ` 3.08 ms` || boolean false -> (100) | `168.24 µs/iter` | `119.42 µs` | `171.92 µs` | `327.38 µs` | ` 3.18 ms` || undefined -> (100) | `174.87 µs/iter` | `122.58 µs` | `180.38 µs` | `324.38 µs` | ` 3.31 ms` || null -> (100) | `177.45 µs/iter` | `122.75 µs` | `183.29 µs` | `318.17 µs` | ` 3.12 ms` || string -> (100) | `172.13 µs/iter` | `121.83 µs` | `175.33 µs` | `311.46 µs` | ` 3.44 ms` || json object -> (100) | `349.71 µs/iter` | `272.13 µs` | `358.25 µs` | `539.25 µs` | ` 3.52 ms` || json array -> (100) | `518.73 µs/iter` | `409.38 µs` | `542.92 µs` | `754.54 µs` | ` 3.59 ms` || Uint8Array -> (100) | `242.72 µs/iter` | `171.54 µs` | `253.50 µs` | `506.21 µs` | ` 2.42 ms` || ArrayBuffer -> (100) | `229.70 µs/iter` | `160.50 µs` | `239.67 µs` | `470.63 µs` | ` 2.41 ms` || Buffer -> (100) | `354.02 µs/iter` | `222.83 µs` | `376.63 µs` | `974.71 µs` | ` 1.47 ms` || string huge -> (100) | `197.79 µs/iter` | `141.29 µs` | `197.08 µs` | `371.71 µs` | ` 2.56 ms` || Int32Array -> (100) | `243.54 µs/iter` | `169.13 µs` | `254.42 µs` | `512.29 µs` | ` 2.56 ms` || Float64Array -> (100) | `243.76 µs/iter` | `170.29 µs` | `254.00 µs` | `541.63 µs` | ` 2.44 ms` || BigInt64Array -> (100) | `242.08 µs/iter` | `170.46 µs` | `252.08 µs` | `527.83 µs` | ` 2.48 ms` || BigUint64Array -> (100) | `241.30 µs/iter` | `168.63 µs` | `253.17 µs` | `481.75 µs` | ` 2.53 ms` || DataView -> (100) | `240.07 µs/iter` | `169.00 µs` | `250.58 µs` | `529.42 µs` | ` 2.49 ms` || Date -> (100) | `174.26 µs/iter` | `124.38 µs` | `178.88 µs` | `325.83 µs` | ` 3.36 ms` |Call growth throughput (Node)
Section titled “Call growth throughput (Node)”This benchmark increases payload size from 32 B up to 1,048,576 B (1 MiB) and reports
batched cost with batch=64.
Using the 1048576 B row (avg) from the batch=64 run, one-way transfer throughput is:
string:46.54 ms/iter->1.44 GB/sUint8Array:8.95 ms/iter->7.50 GB/s
Interpretation:
- In this batched shape, Node’s
Uint8Arraypath is much stronger than its string path. - For 1 MiB binary payloads, Node lands in the
~7.5 GB/srange in this run.
clk: ~3.70 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • call growth batch string (ascii 32..1048576 x4, batch=64) | avg | min | p75 | p99 | max || --------- | ---------------- | ----------- | ----------- | ----------- | ----------- || 32 B | ` 22.96 µs/iter` | ` 14.58 µs` | ` 28.71 µs` | ` 54.04 µs` | `582.58 µs` || 128 B | ` 27.04 µs/iter` | ` 24.48 µs` | ` 27.65 µs` | ` 28.63 µs` | ` 28.94 µs` || 512 B | ` 44.43 µs/iter` | ` 40.30 µs` | ` 46.17 µs` | ` 46.61 µs` | ` 48.79 µs` || 2048 B | `142.37 µs/iter` | `103.71 µs` | `168.75 µs` | `233.46 µs` | `301.04 µs` || 8192 B | `399.94 µs/iter` | `339.63 µs` | `418.25 µs` | `513.25 µs` | ` 1.59 ms` || 32768 B | ` 1.40 ms/iter` | ` 1.28 ms` | ` 1.43 ms` | ` 2.43 ms` | ` 2.56 ms` || 131072 B | ` 7.07 ms/iter` | ` 5.41 ms` | ` 7.39 ms` | ` 11.23 ms` | ` 11.49 ms` || 524288 B | ` 23.22 ms/iter` | ` 21.87 ms` | ` 23.57 ms` | ` 24.56 ms` | ` 25.24 ms` || 1048576 B | ` 46.54 ms/iter` | ` 44.57 ms` | ` 47.59 ms` | ` 47.69 ms` | ` 48.34 ms` |
| • call growth batch uint8array (32..1048576 x4, batch=64) | avg | min | p75 | p99 | max || --------- | ---------------- | ----------- | ----------- | ----------- | ----------- || 32 B | ` 25.21 µs/iter` | ` 15.46 µs` | ` 29.63 µs` | ` 55.04 µs` | `462.75 µs` || 128 B | ` 26.11 µs/iter` | ` 23.47 µs` | ` 25.99 µs` | ` 30.16 µs` | ` 33.14 µs` || 512 B | ` 26.26 µs/iter` | ` 24.79 µs` | ` 26.35 µs` | ` 26.92 µs` | ` 32.01 µs` || 2048 B | ` 81.17 µs/iter` | ` 41.04 µs` | ` 97.46 µs` | `178.63 µs` | ` 4.42 ms` || 8192 B | `181.59 µs/iter` | ` 91.17 µs` | `190.71 µs` | ` 1.10 ms` | ` 3.30 ms` || 32768 B | `431.63 µs/iter` | `178.17 µs` | `370.88 µs` | ` 2.35 ms` | ` 3.21 ms` || 131072 B | ` 1.40 ms/iter` | `777.21 µs` | ` 1.72 ms` | ` 3.20 ms` | ` 3.36 ms` || 524288 B | ` 4.66 ms/iter` | ` 3.53 ms` | ` 5.08 ms` | ` 6.42 ms` | ` 7.07 ms` || 1048576 B | ` 8.95 ms/iter` | ` 7.54 ms` | ` 9.32 ms` | ` 11.37 ms` | ` 12.30 ms` |Efficiency under heavy tasks (Node)
Section titled “Efficiency under heavy tasks (Node)”This stress test computes prime numbers over a large range, then serializes and parses large JSON payloads:
const N = 10_000_000; // search range: [1..N]const CHUNK_SIZE = 250_000;Even under this heavier workload, parallel workers scale well:
main + 1 extra thread:~1.7xfaster than main only.main + 2 extra threads:~2.3xfaster than main only.main + 3 extra threads:~3.0xfaster than main only.main + 4 extra threads:~3.5xfaster than main only.
clk: ~3.72 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • knitting: primes up to 10,000,000 (chunk=250,000) | avg | min | p75 | p99 | max || ----------------------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || main | `959.14 ms/iter` | `955.16 ms` | `959.93 ms` | `961.89 ms` | `963.68 ms` || main + 1 extra threads → full range | `538.28 ms/iter` | `531.37 ms` | `539.87 ms` | `541.65 ms` | `547.02 ms` || main + 2 extra threads → full range | `401.87 ms/iter` | `395.43 ms` | `404.32 ms` | `406.77 ms` | `408.40 ms` || main + 3 extra threads → full range | `317.52 ms/iter` | `311.27 ms` | `319.14 ms` | `323.94 ms` | `327.36 ms` || main + 4 extra threads → full range | `274.21 ms/iter` | `270.63 ms` | `276.88 ms` | `278.30 ms` | `279.69 ms` |All types in Knitting
Section titled “All types in Knitting”This benchmark covers primitive, structured, collection, typed-array, error/date/symbol, promise-arg, and static-vs-dynamic allocator paths.
Results are reported for count 1 and count 100 to show both per-call latency and batched throughput.
Quick takeaways:
- In count
100, primitive-style payloads are usually in the~15-30 µsrange, while heavier structured/collection payloads can be~120-300+ µs. - The static payload path is usually around
2x-4xfaster than dynamic allocator paths (for example: string~3.4x, json~3.0x,Uint8Array~3.6x, symbol~4.1xat count100).
Payload sizes (approximate):
| Payload | Size |
|---|---|
jsonObj | 206 B |
jsonArr | 217 B |
mapPayload | 284 B |
Uint8Array | 1024 B |
Int32Array | 1024 B |
Float64Array | 1024 B |
BigInt64Array | 1024 B |
BigUint64Array | 1024 B |
DataView | 1024 B |
smallU8 | 480 B |
largeU8 | 481 B |
payload sizes (approx bytes): jsonObj: 206 bytes jsonArr: 217 bytes stringHuge: 1024 bytes Uint8Array: 1024 bytes Int32Array: 1024 bytes Float64Array: 1024 bytes BigInt64Array: 1024 bytes BigUint64Array: 1024 bytes DataView: 1024 bytes
clk: ~3.73 GHzcpu: Apple M3 Ultraruntime: node 24.12.0 (arm64-darwin)
| • knitting-types 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (1) | ` 1.16 µs/iter` | `458.00 ns` | ` 1.54 µs` | ` 2.75 µs` | ` 1.63 ms` || bigint small -> (1) | ` 1.05 µs/iter` | `500.00 ns` | ` 1.50 µs` | ` 2.17 µs` | ` 1.26 ms` || bigint large -> (1) | ` 2.48 µs/iter` | ` 1.25 µs` | ` 2.54 µs` | ` 5.58 µs` | ` 4.13 ms` || boolean true -> (1) | `901.13 ns/iter` | `526.34 ns` | ` 1.21 µs` | ` 1.58 µs` | ` 1.60 µs` || boolean false -> (1) | `824.29 ns/iter` | `520.36 ns` | ` 1.03 µs` | ` 1.57 µs` | ` 1.65 µs` || undefined -> (1) | `984.18 ns/iter` | `526.26 ns` | ` 1.32 µs` | ` 1.58 µs` | ` 1.62 µs` || null -> (1) | `847.02 ns/iter` | `525.11 ns` | ` 1.12 µs` | ` 1.57 µs` | ` 1.57 µs` || string -> (1) | ` 1.44 µs/iter` | `583.00 ns` | ` 2.08 µs` | ` 2.75 µs` | ` 1.24 ms` || json object -> (1) | ` 3.47 µs/iter` | ` 2.46 µs` | ` 3.83 µs` | ` 8.04 µs` | ` 1.27 ms` || json array -> (1) | ` 4.65 µs/iter` | ` 3.42 µs` | ` 4.96 µs` | ` 9.92 µs` | ` 1.24 ms` || Uint8Array -> (1) | ` 2.83 µs/iter` | ` 1.13 µs` | ` 3.42 µs` | ` 7.25 µs` | ` 1.28 ms` || ArrayBuffer -> (1) | ` 2.89 µs/iter` | ` 1.42 µs` | ` 3.71 µs` | ` 7.88 µs` | ` 1.31 ms` || Buffer -> (1) | ` 2.54 µs/iter` | ` 1.73 µs` | ` 2.95 µs` | ` 3.55 µs` | ` 3.57 µs` || string huge -> (1) | ` 3.24 µs/iter` | ` 1.92 µs` | ` 4.00 µs` | ` 7.50 µs` | ` 1.24 ms` || Int32Array -> (1) | ` 2.64 µs/iter` | ` 1.13 µs` | ` 3.33 µs` | ` 6.42 µs` | ` 1.27 ms` || Float64Array -> (1) | ` 2.76 µs/iter` | ` 1.38 µs` | ` 3.63 µs` | ` 7.42 µs` | ` 1.43 ms` || BigInt64Array -> (1) | ` 2.53 µs/iter` | ` 1.13 µs` | ` 3.25 µs` | ` 6.25 µs` | ` 1.27 ms` || BigUint64Array -> (1) | ` 2.58 µs/iter` | ` 1.17 µs` | ` 3.29 µs` | ` 6.29 µs` | ` 1.28 ms` || DataView -> (1) | ` 2.70 µs/iter` | ` 1.80 µs` | ` 3.08 µs` | ` 3.53 µs` | ` 3.57 µs` || Date -> (1) | ` 1.10 µs/iter` | `687.13 ns` | ` 1.37 µs` | ` 1.87 µs` | ` 1.96 µs` || Symbol.for -> (1) | ` 1.62 µs/iter` | ` 1.19 µs` | ` 1.84 µs` | ` 2.15 µs` | ` 2.24 µs` |
| • knitting-types 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || number -> (100) | ` 25.45 µs/iter` | ` 15.33 µs` | ` 33.38 µs` | ` 62.25 µs` | ` 1.25 ms` || bigint small -> (100) | ` 27.62 µs/iter` | ` 25.17 µs` | ` 29.19 µs` | ` 30.32 µs` | ` 32.61 µs` || bigint large -> (100) | ` 70.42 µs/iter` | ` 53.38 µs` | ` 73.75 µs` | `134.50 µs` | ` 1.44 ms` || boolean true -> (100) | ` 27.65 µs/iter` | ` 23.07 µs` | ` 29.43 µs` | ` 31.76 µs` | ` 32.41 µs` || boolean false -> (100) | ` 26.79 µs/iter` | ` 24.41 µs` | ` 27.28 µs` | ` 28.78 µs` | ` 29.58 µs` || undefined -> (100) | ` 26.81 µs/iter` | ` 24.37 µs` | ` 27.73 µs` | ` 29.37 µs` | ` 34.09 µs` || null -> (100) | ` 24.44 µs/iter` | ` 21.21 µs` | ` 25.08 µs` | ` 26.05 µs` | ` 28.83 µs` || string -> (100) | ` 35.29 µs/iter` | ` 31.39 µs` | ` 36.22 µs` | ` 38.08 µs` | ` 41.26 µs` || json object -> (100) | `123.26 µs/iter` | `105.54 µs` | `123.92 µs` | `221.92 µs` | ` 1.39 ms` || json array -> (100) | `178.94 µs/iter` | `154.96 µs` | `185.13 µs` | `285.50 µs` | `491.88 µs` || Uint8Array -> (100) | `108.25 µs/iter` | ` 56.88 µs` | `141.25 µs` | `215.38 µs` | ` 3.06 ms` || ArrayBuffer -> (100) | `123.32 µs/iter` | ` 66.17 µs` | `153.63 µs` | `230.04 µs` | ` 2.51 ms` || Buffer -> (100) | `102.49 µs/iter` | ` 57.42 µs` | `139.83 µs` | `215.08 µs` | ` 2.97 ms` || string huge -> (100) | `162.92 µs/iter` | `111.25 µs` | `210.12 µs` | `268.54 µs` | ` 1.44 ms` || Int32Array -> (100) | `103.37 µs/iter` | ` 58.38 µs` | `141.13 µs` | `212.63 µs` | ` 3.04 ms` || Float64Array -> (100) | `121.34 µs/iter` | ` 65.71 µs` | `147.25 µs` | `230.96 µs` | ` 1.85 ms` || BigInt64Array -> (100) | `105.26 µs/iter` | ` 58.75 µs` | `139.79 µs` | `207.92 µs` | ` 3.10 ms` || BigUint64Array -> (100) | `102.90 µs/iter` | ` 59.21 µs` | `140.08 µs` | `203.58 µs` | ` 3.23 ms` || DataView -> (100) | `110.45 µs/iter` | ` 61.42 µs` | `145.21 µs` | `217.79 µs` | ` 2.74 ms` || Date -> (100) | ` 32.51 µs/iter` | ` 29.91 µs` | ` 33.09 µs` | ` 34.62 µs` | ` 38.05 µs` || Symbol.for -> (100) | ` 40.59 µs/iter` | ` 38.45 µs` | ` 41.20 µs` | ` 41.93 µs` | ` 42.32 µs` |
| • knitting-promise-args 1 | avg | min | p75 | p99 | max || --------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || promise number -> (1) | ` 1.65 µs/iter` | ` 1.20 µs` | ` 1.83 µs` | ` 2.12 µs` | ` 2.15 µs` || promise object -> (1) | ` 2.69 µs/iter` | ` 2.20 µs` | ` 2.93 µs` | ` 3.15 µs` | ` 3.16 µs` |
| • knitting-promise-args 100 | avg | min | p75 | p99 | max || ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- || promise number -> (100) | ` 33.41 µs/iter` | ` 30.85 µs` | ` 34.19 µs` | ` 37.45 µs` | ` 37.53 µs` || promise object -> (100) | ` 71.73 µs/iter` | ` 57.46 µs` | ` 77.17 µs` | `139.38 µs` | `253.00 µs` |