GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — fs: read small files in one thread pool round trip by codebytere · Pull Request #65327 · nodejs/node

Conversation

@codebytere

@codebytere codebytere commented Aug 16, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

fs.readFile() / fs.promises.readFile() of small files get 3–6× faster, and use one libuv thread-pool task instead of four, by doing open + fstat + read + close in a single round trip.

fs/readfile.js            len=1024   concurrent=1                    ***   204.95 %  ±2.29%
fs/readfile.js            len=1024   concurrent=10                   ***   299.99 %  ±4.58%
fs/readfile-promises.js   len=1024   concurrent=1                    ***   238.56 %  ±2.68%
fs/readfile-promises.js   len=1024   concurrent=10                   ***   500.14 %  ±5.17%
fs/readfile-promises.js   len=524288 concurrent=10 encoding='utf-8'  ***   132.83 %  ±8.34%
fs/readfile-partitioned.js len=1024  concurrent=10 (vs. zlib work)   ***   240.87 %
fs/readfile*.js           len ≥ 4 MiB                                        ~0 %   n.s. (one exception below)
fs.readFile() of 4 KiB files at concurrency 64:   ~51 k → ~306 k files/s;  mixed with fs.stat + dns.lookup: ~66 k → ~312 k ops/s

(Linux x64, --set duration=2, 30 runs.)

Today a path-based readFile issues open, fstat, read and close as four separate uv_fs_* requests, each with its own queue wait, completion callback and JS↔C++ crossing; the promise API does the same through a FileHandle. For small files those round trips are the whole cost, and each one takes a pool slot away from concurrent dns/zlib/crypto/fs work.

ReadFileJob (an AsyncWrap + ThreadPoolWork, provider FSREQCALLBACK) runs open + fstat + read-to-EOF + close as one task and returns the content. If the file is larger than one chunk (kReadFileBufferLength, 512 KiB) it stops after fstat and hands back the fd and size, and the existing chunked reader continues exactly as today (interleaved, abortable between chunks). Both readFiles use it for path arguments without a user buffer; fds and FileHandles are unchanged.

Preserved on purpose: identical results for every size/encoding; open errors report syscall: 'open' + path, read errors 'read'; permission errors arrive through the callback/promise; an abort that lands while the round trip is in flight still wins; the handed-back fd is tracked and closed like any other; size-0 files (procfs) are read to EOF.

One open point: 16–32 MiB reads via fs.promises.readFile(…, 'utf-8') at concurrency 10 measure −2…3 % (***), reproducibly; the same sizes as Buffers, via the callback API, or at concurrency 1 are flat. They take the hand-back path with identical syscalls, and direct timing shows ≤2 %, so I haven't pinned it down. If preferred, the promise API can keep its current path and only the callback API changes.

Tests: test-fs-readfile-one-roundtrip.js (new; also passes on current main): sizes across the 512 KiB threshold, encodings, flags, error shapes, abort before/during, fd/FileHandle inputs, no fd leak on hand-back, procfs/sysfs, async_hooks lifecycle. Adjusted to keep testing what they test: test/async-hooks/test-fsreqcallback-readFile.js (accepts one request instead of exactly four), test-graph.fsreq-readFile.js (reads a 512 KiB+1 file so the four-request chain keeps its shape), test-async-exec-resource-match.js (resource + ≥1 fs request), test-trace-events-fs-async.js (uses fs.fstat() for the fstat trace instead of readFile as a proxy), test-fs-promises-readfile.js (zero-size-liar case goes through a FileHandle), test-fs-promises-file-handle-{op,aggregate,close}-errors.js (use a >512 KiB file so the patched FileHandle path is taken). fs, async-hooks, permission, worker, process and child_process suites pass.


Disclosure: the code, test, measurements and this description were written by Claude Code, directed and reviewed by @codebytere.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

daniellockyer reacted with rocket emoji
All reactions
  • 🚀 1 reaction
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to file-system APIs and the fs module. needs-ci PRs that need a full CI run. labels Aug 16, 2026
@codebytere
codebytere force-pushed the perf/fs-readfile-one-roundtrip branch from 0eaf058 to 21db0ab Compare August 16, 2026 16:54
@codecov

codecov Bot commented Aug 16, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.55975% with 65 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.10%. Comparing base (30bff4a) to head (b626e93).
⚠️ Report is 43 commits behind head on main.

Files with missing lines Patch % Lines
src/node_file.cc 69.34% 35 Missing and 26 partials ⚠️
lib/internal/fs/promises.js 92.85% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65327      +/-   ##
==========================================
- Coverage   90.13%   90.10%   -0.04%     
==========================================
  Files         752      752              
  Lines      251568   251915     +347     
  Branches    47270    47353      +83     
==========================================
+ Hits       226759   226976     +217     
- Misses      16168    16266      +98     
- Partials     8641     8673      +32     
Files with missing lines Coverage Δ
lib/fs.js 98.39% <100.00%> (+0.02%) ⬆️
lib/internal/fs/promises.js 92.52% <92.85%> (-0.48%) ⬇️
src/node_file.cc 73.92% <69.34%> (-0.27%) ⬇️

... and 37 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@codebytere
codebytere requested review from anonrig and jasnell August 16, 2026 18:36
@codebytere codebytere added request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. and removed needs-ci PRs that need a full CI run. labels Aug 16, 2026
anonrig
anonrig approved these changes Aug 16, 2026
View reviewed changes
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Aug 16, 2026
@nodejs-github-bot

nodejs-github-bot commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/75893/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jasnell
jasnell reviewed Aug 17, 2026
View reviewed changes
Comment thread src/node_file.cc Resolved

Uh oh!

There was an error while loading. Please reload this page.

jasnell
jasnell requested changes Aug 17, 2026
View reviewed changes

@jasnell jasnell left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test failure on AIX needs to be looked at. Also, are these reads actually abortable in any way?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread test/parallel/test-fs-readfile-one-roundtrip.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/node_file.cc Resolved

Uh oh!

There was an error while loading. Please reload this page.

@codebytere
fs: read small files in one thread pool round trip
b626e93
fs.readFile(path) took four libuv thread pool round trips for a typical
small file -- open, fstat, read and close, each its own uv_fs request
with its own queue wait, completion callback and JS/C++ crossing -- and
fs.promises.readFile(path) did the same through a FileHandle. For the
small files applications read most, the round trips are the cost, and
each occupies a slot in the pool that concurrent dns.lookup(), fs and
crypto work is also queueing for.

Add ReadFileJob (an AsyncWrap + ThreadPoolWork) that performs
open + fstat + read-to-EOF + close as one pool task and reports the
whole content, or, when the file turns out to be larger than one chunk
(kReadFileBufferLength, 512 KiB), stops after fstat() and hands the fd
and size back so that the existing chunked reader continues unchanged
(large reads stay interleaved and abortable between chunks, and still
save the fstat round trip). fs.readFile() and fs.promises.readFile()
use it for path arguments without a user buffer; file descriptors,
FileHandles, options.buffer and an active VFS keep their paths.

Behavior is otherwise kept: same bytes for every size and encoding;
open failures report syscall 'open' with the path, read failures
'read'; permission errors are delivered through the callback/promise
as before; an abort that arrives while the read is in flight still
wins; the job is an FSREQCALLBACK resource for async_hooks; a handed
back fd is tracked exactly like one from a plain open().

Tests that asserted the internal open/fstat/read/close request chain,
used readFile() as a proxy for an fstat trace event, or injected
faults through FileHandle.prototype for path-based reads are adjusted
to keep testing what they test (a file just over one chunk where the
chain shape matters, fs.fstat() for the fstat trace, a larger file so
the FileHandle path is taken).

fs.readFile() of 4 KiB files at concurrency 64 goes from ~51k to ~306k
files per second, and a mixed stat/readFile/dns.lookup burst from ~66k
to ~312k operations per second.

Signed-off-by: Shelley Vohr <[email protected]>
@codebytere
codebytere force-pushed the perf/fs-readfile-one-roundtrip branch from 21db0ab to b626e93 Compare August 17, 2026 05:17
@codebytere

codebytere commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

@jasnell re aborts: the single round trip itself isn't interruptible once it's on the pool, same as an individual read req now; an already-aborted signal never schedules it, an abort that lands while it's in flight wins when it completes, and anything over one chunk hands the fd back to the existing chunked reader, so those stay abortable between chunks exactly as before.

jasnell reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jasnell
jasnell approved these changes Aug 17, 2026
View reviewed changes
@codebytere codebytere added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Aug 17, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Aug 17, 2026
@nodejs-github-bot

nodejs-github-bot commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/75946/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/75983/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@codebytere codebytere added the commit-queue PRs queued for automated landing through the Commit Queue. label Aug 19, 2026
@nodejs-github-bot
nodejs-github-bot merged commit 542e2b2 into nodejs:main Aug 19, 2026
70 of 71 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Landed in 542e2b2

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot nodejs-github-bot removed the commit-queue PRs queued for automated landing through the Commit Queue. label Aug 19, 2026
@codebytere codebytere mentioned this pull request Aug 22, 2026
fs: write files in one thread pool round trip #65489
Closed
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
@codebytere @aduh95
fs: read small files in one thread pool round trip
4c93a2c
fs.readFile(path) took four libuv thread pool round trips for a typical
small file -- open, fstat, read and close, each its own uv_fs request
with its own queue wait, completion callback and JS/C++ crossing -- and
fs.promises.readFile(path) did the same through a FileHandle. For the
small files applications read most, the round trips are the cost, and
each occupies a slot in the pool that concurrent dns.lookup(), fs and
crypto work is also queueing for.

Add ReadFileJob (an AsyncWrap + ThreadPoolWork) that performs
open + fstat + read-to-EOF + close as one pool task and reports the
whole content, or, when the file turns out to be larger than one chunk
(kReadFileBufferLength, 512 KiB), stops after fstat() and hands the fd
and size back so that the existing chunked reader continues unchanged
(large reads stay interleaved and abortable between chunks, and still
save the fstat round trip). fs.readFile() and fs.promises.readFile()
use it for path arguments without a user buffer; file descriptors,
FileHandles, options.buffer and an active VFS keep their paths.

Behavior is otherwise kept: same bytes for every size and encoding;
open failures report syscall 'open' with the path, read failures
'read'; permission errors are delivered through the callback/promise
as before; an abort that arrives while the read is in flight still
wins; the job is an FSREQCALLBACK resource for async_hooks; a handed
back fd is tracked exactly like one from a plain open().

Tests that asserted the internal open/fstat/read/close request chain,
used readFile() as a proxy for an fstat trace event, or injected
faults through FileHandle.prototype for path-based reads are adjusted
to keep testing what they test (a file just over one chunk where the
chain shape matters, fs.fstat() for the fstat trace, a larger file so
the FileHandle path is taken).

fs.readFile() of 4 KiB files at concurrency 64 goes from ~51k to ~306k
files per second, and a mixed stat/readFile/dns.lookup burst from ~66k
to ~312k operations per second.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65327
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
@codebytere @aduh95
fs: read small files in one thread pool round trip
77fedbd
fs.readFile(path) took four libuv thread pool round trips for a typical
small file -- open, fstat, read and close, each its own uv_fs request
with its own queue wait, completion callback and JS/C++ crossing -- and
fs.promises.readFile(path) did the same through a FileHandle. For the
small files applications read most, the round trips are the cost, and
each occupies a slot in the pool that concurrent dns.lookup(), fs and
crypto work is also queueing for.

Add ReadFileJob (an AsyncWrap + ThreadPoolWork) that performs
open + fstat + read-to-EOF + close as one pool task and reports the
whole content, or, when the file turns out to be larger than one chunk
(kReadFileBufferLength, 512 KiB), stops after fstat() and hands the fd
and size back so that the existing chunked reader continues unchanged
(large reads stay interleaved and abortable between chunks, and still
save the fstat round trip). fs.readFile() and fs.promises.readFile()
use it for path arguments without a user buffer; file descriptors,
FileHandles, options.buffer and an active VFS keep their paths.

Behavior is otherwise kept: same bytes for every size and encoding;
open failures report syscall 'open' with the path, read failures
'read'; permission errors are delivered through the callback/promise
as before; an abort that arrives while the read is in flight still
wins; the job is an FSREQCALLBACK resource for async_hooks; a handed
back fd is tracked exactly like one from a plain open().

Tests that asserted the internal open/fstat/read/close request chain,
used readFile() as a proxy for an fstat trace event, or injected
faults through FileHandle.prototype for path-based reads are adjusted
to keep testing what they test (a file just over one chunk where the
chain shape matters, fs.fstat() for the fstat trace, a larger file so
the FileHandle path is taken).

fs.readFile() of 4 KiB files at concurrency 64 goes from ~51k to ~306k
files per second, and a mixed stat/readFile/dns.lookup burst from ~66k
to ~312k operations per second.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65327
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@github-actions github-actions Bot mentioned this pull request Aug 25, 2026
2026-08-26, Version 26.8.0 (Current) #65551
Merged
@lumirlumir lumirlumir mentioned this pull request Aug 29, 2026
Change Request: re-enable the EMFILE test on Node.js 26.8+ eslint/eslint#21274
Closed
1 of 3 tasks
@sheremet-va sheremet-va mentioned this pull request Aug 29, 2026
test: use fs.watch for the async leak fixture vitest-dev/vitest#11099
Merged
davidgamero added a commit to davidgamero/javascript that referenced this pull request Aug 30, 2026
@davidgamero
ci: pin the Node 26 matrix entry to 26.7
0eb1a9a
Node 26.8.0 rewrote fs.readFile (nodejs/node#65327) to do open, fstat,
read and close in a single thread pool round trip, so binding.open is no
longer called from JS. mock-fs recovers the ReadFileContext prototype by
intercepting binding.open during a dummy readFile, so it now gets
undefined and throws at require time:

    TypeError: Cannot read properties of undefined (reading 'read')
        at exports.patchReadFileContext (mock-fs/lib/readfilecontext.js:40:30)

Because it throws on require rather than in a test, it takes out
config_test.ts and file_auth_test.ts in full.

The matrix entries are floating majors, so setup-node resolves '26' to
whatever the newest 26.x is at run time. That is why main went red on
the merge of kubernetes-client#3022 without any change to the code under test: the branch
last ran CI on 26.7.0, and by the time it merged five days later the
runner had picked up 26.8.1.

Pinning to 26.7 restores a green build. It is a stopgap: mock-fs has had
no functional release since February 2025 and the upstream report
(tschaub/mock-fs#447) is unanswered, so the durable fix is to stop
depending on it.
@uncoolclub uncoolclub mentioned this pull request Sep 2, 2026
ci: restore EMFILE test on Node.js 26 eslint/eslint#21297
Merged
2 of 3 tasks
codebytere added a commit that referenced this pull request Sep 3, 2026
@codebytere
fs: write files in one thread pool round trip
e324419
fs.writeFile(path, data) took three libuv thread pool round trips
(open, write, close), each its own request with its own queue wait,
completion callback and JS/C++ crossing, and fs.promises.writeFile()
did the same through a FileHandle. For the small files applications
write most, the round trips are the cost, and each occupies a pool slot
that concurrent fs, dns.lookup() and crypto work is also queueing for.

Add WriteFileJob next to ReadFileJob: an AsyncWrap + ThreadPoolWork
that opens, writes the whole buffer (looping on short writes) and
closes as one pool task, keeping the buffer alive until it is done.
fs.writeFile() uses it for path arguments without flush;
fs.promises.writeFile() additionally keeps data above one write chunk
(and iterables) on the FileHandle path, so large writes stay abortable
between chunks as before. File descriptors, FileHandles, flush: true
and an active VFS keep their existing paths.

Behavior is otherwise kept: open failures report syscall 'open' with
the path, write failures 'write'; permission errors are delivered
through the callback/promise; an abort signalled while the write is in
flight is still reported as an AbortError; the job is an FSREQCALLBACK
resource for async_hooks and emits the 'write' fs trace event.

Tests that used fs.writeFile() as a proxy for open/close trace events,
or injected FileHandle faults for path-based writes, are adjusted to
keep testing what they test.

The job holds the buffer's backing store, so the memory stays valid if
the buffer is detached or collected before the write finishes; a
resizable ArrayBuffer could still have its pages decommitted by a
shrink, so its contents are copied when the job is created.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65489
Refs: #65327
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
aduh95 pushed a commit that referenced this pull request Sep 7, 2026
@codebytere @aduh95
fs: write files in one thread pool round trip
bb4d42c
fs.writeFile(path, data) took three libuv thread pool round trips
(open, write, close), each its own request with its own queue wait,
completion callback and JS/C++ crossing, and fs.promises.writeFile()
did the same through a FileHandle. For the small files applications
write most, the round trips are the cost, and each occupies a pool slot
that concurrent fs, dns.lookup() and crypto work is also queueing for.

Add WriteFileJob next to ReadFileJob: an AsyncWrap + ThreadPoolWork
that opens, writes the whole buffer (looping on short writes) and
closes as one pool task, keeping the buffer alive until it is done.
fs.writeFile() uses it for path arguments without flush;
fs.promises.writeFile() additionally keeps data above one write chunk
(and iterables) on the FileHandle path, so large writes stay abortable
between chunks as before. File descriptors, FileHandles, flush: true
and an active VFS keep their existing paths.

Behavior is otherwise kept: open failures report syscall 'open' with
the path, write failures 'write'; permission errors are delivered
through the callback/promise; an abort signalled while the write is in
flight is still reported as an AbortError; the job is an FSREQCALLBACK
resource for async_hooks and emits the 'write' fs trace event.

Tests that used fs.writeFile() as a proxy for open/close trace events,
or injected FileHandle faults for path-based writes, are adjusted to
keep testing what they test.

The job holds the buffer's backing store, so the memory stays valid if
the buffer is detached or collected before the write finishes; a
resizable ArrayBuffer could still have its pages decommitted by a
shrink, so its contents are copied when the job is created.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65489
Refs: #65327
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
aduh95 pushed a commit that referenced this pull request Sep 7, 2026
@codebytere @aduh95
fs: write files in one thread pool round trip
9a6bef4
fs.writeFile(path, data) took three libuv thread pool round trips
(open, write, close), each its own request with its own queue wait,
completion callback and JS/C++ crossing, and fs.promises.writeFile()
did the same through a FileHandle. For the small files applications
write most, the round trips are the cost, and each occupies a pool slot
that concurrent fs, dns.lookup() and crypto work is also queueing for.

Add WriteFileJob next to ReadFileJob: an AsyncWrap + ThreadPoolWork
that opens, writes the whole buffer (looping on short writes) and
closes as one pool task, keeping the buffer alive until it is done.
fs.writeFile() uses it for path arguments without flush;
fs.promises.writeFile() additionally keeps data above one write chunk
(and iterables) on the FileHandle path, so large writes stay abortable
between chunks as before. File descriptors, FileHandles, flush: true
and an active VFS keep their existing paths.

Behavior is otherwise kept: open failures report syscall 'open' with
the path, write failures 'write'; permission errors are delivered
through the callback/promise; an abort signalled while the write is in
flight is still reported as an AbortError; the job is an FSREQCALLBACK
resource for async_hooks and emits the 'write' fs trace event.

Tests that used fs.writeFile() as a proxy for open/close trace events,
or injected FileHandle faults for path-based writes, are adjusted to
keep testing what they test.

The job holds the buffer's backing store, so the memory stays valid if
the buffer is detached or collected before the write finishes; a
resizable ArrayBuffer could still have its pages decommitted by a
shrink, so its contents are copied when the job is created.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65489
Refs: #65327
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
alexkli added a commit to adobe/sizewatcher that referenced this pull request Sep 11, 2026
@alexkli @claude
replace mock-fs with real temp dirs in config tests
0a95ba4
mock-fs 5.5.0 throws at require time on Node 26.8+ because
nodejs/node#65327 rewrote fs.readFile and the prototype sniffing in
mock-fs no longer finds ReadFileContext (tschaub/mock-fs#447, unfixed).

The config tests now write .sizewatcher.yml into a fresh tmp directory
and chdir into it, matching the pattern already used in cli.test.js.
This removes the mock-fs devDependency entirely.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@alexkli alexkli mentioned this pull request Sep 11, 2026
Fix broken tests on latest Node 26.8 adobe/sizewatcher#150
Merged
alexkli added a commit to adobe/sizewatcher that referenced this pull request Sep 11, 2026
@alexkli @claude
replace mock-fs with real temp dirs in config tests
e5db996
mock-fs 5.5.0 throws at require time on Node 26.8+ because
nodejs/node#65327 rewrote fs.readFile and the prototype sniffing in
mock-fs no longer finds ReadFileContext (tschaub/mock-fs#447, unfixed).

The config tests now write .sizewatcher.yml into a fresh tmp directory
and chdir into it, matching the pattern already used in cli.test.js.
This removes the mock-fs devDependency entirely.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@anurag6569201 anurag6569201 mentioned this pull request Sep 12, 2026
ci: restore EMFILE test on Node.js 26 ShipWright-Review/eslint#2
Open
2 of 3 tasks
aduh95 pushed a commit that referenced this pull request Sep 15, 2026
@codebytere @aduh95
fs: write files in one thread pool round trip
6ac1bc0
fs.writeFile(path, data) took three libuv thread pool round trips
(open, write, close), each its own request with its own queue wait,
completion callback and JS/C++ crossing, and fs.promises.writeFile()
did the same through a FileHandle. For the small files applications
write most, the round trips are the cost, and each occupies a pool slot
that concurrent fs, dns.lookup() and crypto work is also queueing for.

Add WriteFileJob next to ReadFileJob: an AsyncWrap + ThreadPoolWork
that opens, writes the whole buffer (looping on short writes) and
closes as one pool task, keeping the buffer alive until it is done.
fs.writeFile() uses it for path arguments without flush;
fs.promises.writeFile() additionally keeps data above one write chunk
(and iterables) on the FileHandle path, so large writes stay abortable
between chunks as before. File descriptors, FileHandles, flush: true
and an active VFS keep their existing paths.

Behavior is otherwise kept: open failures report syscall 'open' with
the path, write failures 'write'; permission errors are delivered
through the callback/promise; an abort signalled while the write is in
flight is still reported as an AbortError; the job is an FSREQCALLBACK
resource for async_hooks and emits the 'write' fs trace event.

Tests that used fs.writeFile() as a proxy for open/close trace events,
or injected FileHandle faults for path-based writes, are adjusted to
keep testing what they test.

The job holds the buffer's backing store, so the memory stays valid if
the buffer is detached or collected before the write finishes; a
resizable ArrayBuffer could still have its pages decommitted by a
shrink, so its contents are copied when the job is created.

Signed-off-by: Shelley Vohr <[email protected]>
PR-URL: #65489
Refs: #65327
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
@vedchaudhari vedchaudhari mentioned this pull request Oct 15, 2026
fs: restore stack traces of fs/promises readFile and writeFile errors #66757
Merged
@christianaurichzm christianaurichzm mentioned this pull request Oct 23, 2026
fs: keep readFile abortable on non-regular files #66940
Merged
@mcrowder65 mcrowder65 mentioned this pull request Oct 23, 2026
chore: move toolchain to Node 26.12.1 (October 2026 security release) mcrowder65/immich-trim#2
Merged
This was referenced Oct 25, 2026
Netlify build fails with "Could not patch functions config manifest file" on Node.js 26.8+ Alice39s/kuma-mieru#505
Open
fix: create server dir before patching functions-config-manifest.json opennextjs/opennextjs-netlify#3599
Merged
netlify build fails with "Could not patch functions config manifest file" on Node.js 26.8+ with Node.js middleware opennextjs/opennextjs-netlify#3600
Closed
@3zrv 3zrv mentioned this pull request Oct 29, 2026
fs: harden the one-round-trip read and write jobs #67112
Open
SaigyoujYuyuko added a commit to SaigyoujYuyuko/ayafileio that referenced this pull request Oct 30, 2026
@SaigyoujYuyuko
perf(whole): read_bytes / read_bytes_many 改为原生单跳作业(1.71x)
5cf9ffd
读整文件原本每文件三次往返:aopen -> read -> close,每次都是一轮「提交 -> 完成包 ->
回到事件循环」。现在一个线程池任务里做完 open + size + read + close 并交回字节
(py_read_whole_async),形状对齐 Node.js nodejs/node#65327(ReadFileJob)。

实测(Windows、4 KiB 文件、并发 64、SATA SSD):
* read_bytes_many(公开 API)  13,092 -> 22,367 files/s   1.71x
* 裸 read_whole_async           12,091 -> 25,585 files/s   2.12x

两个反直觉的点,一并记进 changelog:
1) 最直觉的 Python 实现 asyncio.to_thread(同步整读) 比要替换的代码**慢一倍**
   (6.7k vs 13.1k files/s)。我们的跳是 IOCP 完成包,比「线程池提交 + GIL 往返」
   便宜,用 to_thread 等于拿贵机制换便宜机制。
2) 每跳成本约 25-35 us,主要由 Python future 与事件循环转身决定,不是 syscall;
   压跳数之所以划算正因如此。

语义保持不变,新增 tests/python/test_whole_read.py(12 项)以**异步路径为基准**逐条
对照:0/1/4095/4096/700000 字节内容、PathLike/str 入参、缺失文件与目录的异常类型、
errno 与文案("Failed to open file: <path>" 逐字节一致)、顺序保持、失败传播、
句柄泄漏计数。文本系列与 write_bytes 仍走异步后端。

架构:新文件 src/bindings/python/py_whole.cpp 走 platform/native_file.hpp(组合根
allow: ["*"]),架构守卫 82 文件 / 169 includes 通过。

验证:全套连跑 3 次 367 passed(+12);强制完成包路径 367 passed;
thread_pool 365 passed;ctest 3/3;架构守卫 OK。
vedchaudhari added a commit to vedchaudhari/node that referenced this pull request Oct 31, 2026
@vedchaudhari
fs: restore stack traces of fs/promises readFile and writeFile errors
42e6ebd
Errors from readFile(), writeFile() and appendFile() have had no stack
frames since they started using a single thread pool round trip, as
the stack was captured from a C++ callback with no JS frames on it.
Capture it after the await instead, like the rest of fs/promises.

Refs: nodejs#65327
Refs: nodejs#65489
Assisted-by: claude:opus-5.5
Signed-off-by: vedchaudhari <[email protected]>
vedchaudhari added a commit to vedchaudhari/node that referenced this pull request Oct 31, 2026
@vedchaudhari
fs: restore stack traces of fs/promises readFile and writeFile errors
b9df2e3
Errors from readFile(), writeFile() and appendFile() have had no stack
frames since they started using a single thread pool round trip, as
the stack was captured from a C++ callback with no JS frames on it.
Capture it after the await instead, like the rest of fs/promises.

Refs: nodejs#65327
Refs: nodejs#65489
Assisted-by: claude:opus-5.5
Signed-off-by: vedchaudhari <[email protected]>
@mrgrain mrgrain mentioned this pull request Nov 3, 2026
chore(integ-runner): unit tests fail on Node 26.8+ because mock-fs cannot load aws/aws-cdk-cli#2117
Merged
1 task
mrgrain added a commit to abhiramshaji-cyber/aws-cdk-cli that referenced this pull request Nov 3, 2026
@mrgrain
chore(integ-runner): unit tests fail on Node 26.8+ because mock-fs ca…
58a3bb3
…nnot load (aws#2117)

Fixes #

On Node 26.8 and later, the integ-runner unit tests that use `mock-fs`
fail before any test runs:

```
TypeError: Cannot read properties of undefined (reading 'read')
    at exports.patchReadFileContext (mock-fs/lib/readfilecontext.js:40:30)
```

`mock-fs` patches Node.js `fs` internals, and
[nodejs/node#65327](nodejs/node#65327) changed
`fs.readFile` so that the internal hook `mock-fs` relies on no longer
fires. The library now throws as soon as it is required
([tschaub/mock-fs#447](tschaub/mock-fs#447)).
There is no fixed release.

The affected tests in `integ-runner` now write their fixtures into real
temp directories created with `fs.mkdtempSync`, the same approach other
tests in the repo already use. `mock-fs` is removed as a dev dependency
from `integ-runner`, `cdk-assets-lib` and `cloud-assembly-schema`, which
no longer import it. Also includes a lint fix for import order in
`toolkit-lib`'s `base-credentials.ts`.

### Checklist
- [ ] This change contains a major version upgrade for a dependency and
I confirm all breaking changes are addressed
  - Release notes for the new version:

---
By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache-2.0 license
@onigoetz onigoetz mentioned this pull request Nov 7, 2026
Fix tests on Node.js 26 swissquote/crafty#3386
Merged
nodejs-github-bot pushed a commit that referenced this pull request Nov 10, 2026
@christianaurichzm
fs: keep readFile abortable on non-regular files
6c8a697
`ReadFileJob` treats a file that is not a regular file as size 0 and
reads it to EOF inside one thread pool job, so the `AbortSignal` is
only checked once the job ends. `fs.readFile()` and
`fs.promises.readFile()` on a FIFO whose writer stays open therefore
do not settle until the writer closes, and on `/dev/zero` they keep
growing the buffer until the process runs out of memory.

Hand the fd back to the chunked reader for non-regular files, the path
files larger than one chunk already take. It checks the signal before
each read. Regular files that report size 0, such as procfs files, are
still read in one job.

Signed-off-by: Christian Aurich Zanettini Martins <[email protected]>
PR-URL: #66940
Refs: #65327
Reviewed-By: Anna Henningsen <[email protected]>
aduh95 pushed a commit that referenced this pull request Nov 11, 2026
@christianaurichzm @aduh95
fs: keep readFile abortable on non-regular files
0c5be92
`ReadFileJob` treats a file that is not a regular file as size 0 and
reads it to EOF inside one thread pool job, so the `AbortSignal` is
only checked once the job ends. `fs.readFile()` and
`fs.promises.readFile()` on a FIFO whose writer stays open therefore
do not settle until the writer closes, and on `/dev/zero` they keep
growing the buffer until the process runs out of memory.

Hand the fd back to the chunked reader for non-regular files, the path
files larger than one chunk already take. It checks the signal before
each read. Regular files that report size 0, such as procfs files, are
still read in one job.

Signed-off-by: Christian Aurich Zanettini Martins <[email protected]>
PR-URL: #66940
Refs: #65327
Reviewed-By: Anna Henningsen <[email protected]>
nodejs-github-bot pushed a commit that referenced this pull request Nov 11, 2026
@vedchaudhari
fs: restore stack traces of fs/promises readFile and writeFile errors
933cb11
Errors from readFile(), writeFile() and appendFile() have had no stack
frames since they started using a single thread pool round trip, as
the stack was captured from a C++ callback with no JS frames on it.
Capture it after the await instead, like the rest of fs/promises.

Refs: #65327
Refs: #65489
Assisted-by: claude:opus-5.5
Signed-off-by: vedchaudhari <[email protected]>
PR-URL: #66757
Reviewed-By: Christian Aurich Zanettini Martins <[email protected]>
Reviewed-By: Gürgün Dayıoğlu <[email protected]>
aduh95 pushed a commit that referenced this pull request Nov 12, 2026
@christianaurichzm @aduh95
fs: keep readFile abortable on non-regular files
3c5f22b
`ReadFileJob` treats a file that is not a regular file as size 0 and
reads it to EOF inside one thread pool job, so the `AbortSignal` is
only checked once the job ends. `fs.readFile()` and
`fs.promises.readFile()` on a FIFO whose writer stays open therefore
do not settle until the writer closes, and on `/dev/zero` they keep
growing the buffer until the process runs out of memory.

Hand the fd back to the chunked reader for non-regular files, the path
files larger than one chunk already take. It checks the signal before
each read. Regular files that report size 0, such as procfs files, are
still read in one job.

Signed-off-by: Christian Aurich Zanettini Martins <[email protected]>
PR-URL: #66940
Refs: #65327
Reviewed-By: Anna Henningsen <[email protected]>
aduh95 pushed a commit that referenced this pull request Nov 12, 2026
@christianaurichzm @aduh95
fs: keep readFile abortable on non-regular files
d59e71d
`ReadFileJob` treats a file that is not a regular file as size 0 and
reads it to EOF inside one thread pool job, so the `AbortSignal` is
only checked once the job ends. `fs.readFile()` and
`fs.promises.readFile()` on a FIFO whose writer stays open therefore
do not settle until the writer closes, and on `/dev/zero` they keep
growing the buffer until the process runs out of memory.

Hand the fd back to the chunked reader for non-regular files, the path
files larger than one chunk already take. It checks the signal before
each read. Regular files that report size 0, such as procfs files, are
still read in one job.

Signed-off-by: Christian Aurich Zanettini Martins <[email protected]>
PR-URL: #66940
Refs: #65327
Reviewed-By: Anna Henningsen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@jasnell jasnell jasnell approved these changes
@anonrig anonrig anonrig approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to file-system APIs and the fs module.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@codebytere @nodejs-github-bot @jasnell @anonrig
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.