Skip to content

Add an opt-in --stdout-buffering build option for line-heavy stdout - #2960

Merged
ctate merged 2 commits into
mainfrom
ctate/add-opt-stdout-f4df90
Nov 4, 2026
Merged

ctate merged 2 commits into
mainfrom
ctate/add-opt-stdout-f4df90

Conversation

@ctate

@ctate ctate commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator
  • scriptc build --stdout-buffering keeps console and process.stdout bytes in the existing 64 KiB buffer when stdout is not a terminal; a terminal keeps one write per call, and builds without the option are unchanged.
  • The buffer settles when it fills, before stderr, when the event loop sleeps, before a blocking stdin read, before process.kill, on process.exit and on an uncaught error, so 2>&1 order and prompt-then-read match Node; a SIGKILL can lose up to 64 KiB.
  • 10M console.log lines to a pipe: 0.54 s with the option, 6.3 s without, 19.0 s in Node 24 (11.8x faster than the default build); fasta n=1M 11.2% faster (13.4% on the ABBA arm means), log-lines 3.35x faster.

A build that sets it keeps console and process.stdout bytes in the
runtime's 64 KiB buffer when stdout is not a terminal. The buffer settles
when it fills, before any stderr write, when the event loop sleeps, before
a blocking stdin read, before process.kill, on process.exit and on an
uncaught error, and at exit; a terminal keeps one write per call. Builds
without the option are unchanged.
@vercel

vercel Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
scriptc Ready Ready Preview, v0 Nov 4, 2026 6:10am UTC

Comment thread packages/runtime/src/scr_async.c Resolved
Comment thread packages/runtime/src/scr_console.c Resolved
--stdout-buffering settled buffered stdout only in the event loop's poll
arm, so a loop waiting on a timer or on a child slept with lines still in
the buffer. The settle now runs before whichever wait arm the loop takes.

Buffered bytes also move from the C stream buffer to a runtime-owned
buffer submitted through the loop that retries EINTR and continues short
writes, because fflush(3) drops the stream's remaining bytes when a
handled signal interrupts a write that transferred nothing. Every place
the runtime flushed the C stream to publish stdout now settles that buffer
first, so process.exit, an uncaught error, a warning, a child inheriting
stdout and the exit hook all publish what the program wrote, and stdout
keeps its order against stderr on a shared descriptor.
@ctate
ctate merged commit a35ffdd into main Nov 4, 2026
74 of 76 checks passed
@ctate
ctate deleted the ctate/add-opt-stdout-f4df90 branch November 4, 2026 07:14

This branch was successfully deployed

1 active deployment
Preview — b26942dd Deployed Nov 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant