Every console.log/error/warn line and process.stdout/stderr.write chunk
is still submitted before the call returns, as in Node. On POSIX
executables, each one now goes out as exactly one write(2) on fd 1 or 2.
Before, it went through C stdio, which cost a copy into the stdio
buffer, one stream call per argument, separator, and newline, and a
flush. stderr is unbuffered, so console.error made one write(2) per
piece: 3 writes per line on average in the probe.
- The line renders into a 2 KiB stack buffer (heap above that). A large
single string goes out with writev and no copy.
- Short writes continue and EINTR retries. Other errors (EAGAIN, EPIPE,
EBADF) return errno with the rest dropped, which is what the stdio
flush did. console still ignores them, and SIGPIPE behavior is
unchanged.
- Runtime-internal bytes still in the C stdout buffer are flushed first
(__fpending on Linux, the FILE fields on Darwin, an unconditional
flush elsewhere), so stdout order and merged 2>&1 order are kept.
- Windows, WASI, and library artifacts keep the C stream path, now fed
one formatted chunk per call.
Tests: corpus 4294 covers line sizes across the stack buffer and the
64 KiB stdio buffer. New console-io harness cases cover stdout and
stderr merged into one pipe and into one file (byte-compared with
Node), and console.log after the stdout reader closes (EPIPE).
Linux sandbox, ns per line (median of 9 launches, 200k lines; scriptc
includes ~1 ms startup). All outputs byte-identical to Node.
probe target node prev cand
p-str pipe 4040 1323 1239
p-str file 3092 849 790
p-str null 2193 319 283
p-args pipe 6168 1440 1228
p-args file 4896 925 802
p-args null 3916 389 292
p-write pipe 2889 1328 1197
p-write file 2267 809 769
p-write null 1577 297 265
p-err pipe 4672 3253 1132
p-err file 3478 2042 717
p-err null 2614 562 232
log-lines pipe 4958 1490 1356
log-lines file 3885 966 877
log-lines null 2983 425 368
strace -c (pipe): p-err went from 600,000 to 200,000 write calls. The
other probes stay at one write per line.