diff --git a/bench/snippets/process-stdin-startup.mjs b/bench/snippets/process-stdin-startup.mjs new file mode 100644 index 0000000000..9b0cee8ae9 --- /dev/null +++ b/bench/snippets/process-stdin-startup.mjs @@ -0,0 +1,49 @@ +// Measures the startup cost of accessing process.stdin +// Each iteration spawns a fresh subprocess to avoid module cache effects. +import { spawnSync } from "bun"; + +const BUN = process.execPath; +const N = 50; + +function measure(label, code) { + const times = []; + for (let i = 0; i < N; i++) { + const result = spawnSync({ + cmd: [BUN, "-e", code], + stdout: "pipe", + stderr: "pipe", + }); + const t = parseFloat(new TextDecoder().decode(result.stdout)); + if (!isNaN(t)) times.push(t); + } + times.sort((a, b) => a - b); + const median = times[Math.floor(times.length / 2)]; + const mean = times.reduce((a, b) => a + b, 0) / times.length; + const min = times[0]; + const max = times[times.length - 1]; + const p95 = times[Math.floor(times.length * 0.95)]; + console.log( + `${label.padEnd(30)} median=${median.toFixed(3)}ms mean=${mean.toFixed(3)}ms min=${min.toFixed(3)}ms max=${max.toFixed(3)}ms p95=${p95.toFixed(3)}ms (n=${times.length})`, + ); +} + +console.log(`Bun: ${BUN}`); +console.log(`Iterations: ${N}\n`); + +// Baseline: empty script (process startup overhead only) +measure("baseline (empty)", `process.stdout.write(String(0))`); + +// Access process.stdin which triggers internal/fs/streams + node:stream loading +measure("process.stdin", `const t=performance.now();process.stdin;process.stdout.write(String(performance.now()-t))`); + +// Also measure require("node:stream") directly +measure( + "require('node:stream')", + `const t=performance.now();require('node:stream');process.stdout.write(String(performance.now()-t))`, +); + +// Measure just require("node:fs").createReadStream (also loads internal/fs/streams) +measure( + "fs.createReadStream", + `const t=performance.now();require('node:fs').createReadStream;process.stdout.write(String(performance.now()-t))`, +); diff --git a/src/js/internal/fs/streams.ts b/src/js/internal/fs/streams.ts index 939ce1153e..9bd70ef10f 100644 --- a/src/js/internal/fs/streams.ts +++ b/src/js/internal/fs/streams.ts @@ -1,6 +1,8 @@ // fs.ReadStream and fs.WriteStream are lazily loaded to avoid importing 'node:stream' until required import type { FileSink } from "bun"; -const { Readable, Writable, finished } = require("node:stream"); +const Readable = require("internal/streams/readable"); +const Writable = require("internal/streams/writable"); +const { finished } = require("internal/streams/end-of-stream"); const fs: typeof import("node:fs") = require("node:fs"); const { read, write, fsync, writev } = fs; const { FileHandle, kRef, kUnref, kFd } = (fs.promises as any).$data as {