Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs: improve readFileSync with file descriptors #49691

Merged
merged 2 commits into from
Sep 25, 2023

Conversation

anonrig
Copy link
Member

@anonrig anonrig commented Sep 17, 2023

This particular change applies to: fs.readFileSync(fs.openSync(__filename), 'utf8')

My local benchmarks are as follows:

fs/readFileSync.js n=10000 hasFileDescriptor='false' path='existing' encoding='undefined'                     0.73 %       ±1.65% ±2.20% ±2.86%
fs/readFileSync.js n=10000 hasFileDescriptor='false' path='existing' encoding='utf8'                          0.05 %       ±1.74% ±2.32% ±3.02%
fs/readFileSync.js n=10000 hasFileDescriptor='false' path='non-existing' encoding='undefined'        ***     62.27 %       ±2.82% ±3.77% ±4.95%
fs/readFileSync.js n=10000 hasFileDescriptor='false' path='non-existing' encoding='utf8'             ***     60.93 %       ±2.72% ±3.64% ±4.78%
fs/readFileSync.js n=10000 hasFileDescriptor='true' path='existing' encoding='undefined'                      0.22 %       ±1.47% ±1.96% ±2.56%
fs/readFileSync.js n=10000 hasFileDescriptor='true' path='existing' encoding='utf8'                  ***     88.18 %       ±2.56% ±3.43% ±4.49%
fs/readFileSync.js n=10000 hasFileDescriptor='true' path='non-existing' encoding='undefined'                 -3.31 %       ±4.32% ±5.80% ±7.65%
fs/readFileSync.js n=10000 hasFileDescriptor='true' path='non-existing' encoding='utf8'                      -3.18 %       ±3.58% ±4.79% ±6.30%

Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1413

@anonrig anonrig added the performance Issues and PRs related to the performance of Node.js. label Sep 17, 2023
@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 the fs subsystem / file system. needs-ci PRs that need a full CI run. labels Sep 17, 2023
@rluvaton rluvaton added the needs-benchmark-ci PR that need a benchmark CI run. label Sep 17, 2023
@rluvaton
Copy link
Member

@bnoordhuis
Copy link
Member

Test failures look related.

Correctness issue: file descriptors are int32, not uint32 (also on Windows, because they go through libuv.)

@anonrig
Copy link
Member Author

anonrig commented Sep 18, 2023

@bnoordhuis We validate file descriptors on lib/fs.js by checking if it is Uint32 (ref: https://github.com/nodejs/node/blob/main/lib/fs.js#L204).

@bnoordhuis
Copy link
Member

Apparently that goes back to commit 0803962 from 2015... still wrong though. :-)

(Mostly harmless although technically signed integer overflow is UB in C++.)

@anonrig
Copy link
Member Author

anonrig commented Sep 18, 2023

still wrong though. :-)

Nice find! I'll update the pull request.

@RafaelGSS I'm getting some weird failed test cases where stdout and stderr are both empty in the failing cases, but returning a status of 1. Any idea?

AssertionError [ERR_ASSERTION]
    at Object.<anonymous> (/Users/runner/work/node/node/test/parallel/test-permission-fs-read.js:42:10)
    at Module._compile (node:internal/modules/cjs/loader:1264:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1318:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:954:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:80:12)
    at node:internal/main/run_main_module:23:47 {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: null,
  expected: 0,
  operator: 'strictEqual'
}

@anonrig anonrig force-pushed the fs-read-file-sync-fd branch 2 times, most recently from 0dfcfa4 to de56591 Compare September 18, 2023 19:53
src/node_file.cc Outdated Show resolved Hide resolved
@anonrig anonrig added the request-ci Add this label to start a Jenkins CI on a PR. label Sep 24, 2023
@anonrig
Copy link
Member Author

anonrig commented Sep 24, 2023

Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1413

09:17:21                                                                                               confidence improvement accuracy (*)    (**)   (***)
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='false' path='existing' encoding='undefined'                    -2.80 %       ±8.78% ±11.68% ±15.21%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='false' path='existing' encoding='utf8'                         -6.68 %       ±9.49% ±12.63% ±16.44%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='false' path='non-existing' encoding='undefined'                -3.47 %       ±9.74% ±12.97% ±16.88%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='false' path='non-existing' encoding='utf8'                     -5.20 %       ±8.47% ±11.26% ±14.66%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='true' path='existing' encoding='undefined'                     -1.99 %       ±4.82%  ±6.41%  ±8.34%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='true' path='existing' encoding='utf8'                  ***    126.70 %      ±16.25% ±21.75% ±28.56%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='true' path='non-existing' encoding='undefined'                 -1.31 %       ±6.23%  ±8.29% ±10.79%
09:17:21 fs/readFileSync.js n=10000 hasFileDescriptor='true' path='non-existing' encoding='utf8'              ***    143.95 %      ±18.72% ±25.19% ±33.36%

@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Sep 24, 2023
@nodejs-github-bot
Copy link
Collaborator

@anonrig
Copy link
Member Author

anonrig commented Sep 24, 2023

@nodejs/cpp-reviewers @nodejs/fs Can you review?

CHECK_EQ(0, uv_fs_close(nullptr, &req, file, nullptr));
FS_SYNC_TRACE_END(close);
}
uv_fs_req_cleanup(&req);
Copy link
Member

Choose a reason for hiding this comment

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

For correctness reasons this ought to be done after the uv_fs_read() call on line 2590. It works okay now because libuv doesn't allocate for a single buffer (i.e. this cleanup call is a no-op) but that's a lucky accident.

Copy link
Member Author

Choose a reason for hiding this comment

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

Does that mean that on every while loop iteration (for uv_fs_read), we need to call uv_fs_req_cleanup?

Copy link
Member

Choose a reason for hiding this comment

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

Yes.

@anonrig anonrig added the commit-queue Add this label to land a pull request using GitHub Actions. label Sep 25, 2023
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Sep 25, 2023
@nodejs-github-bot nodejs-github-bot merged commit f16f41c into nodejs:main Sep 25, 2023
55 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in f16f41c

@targos
Copy link
Member

targos commented Sep 26, 2023

@anonrig Please always post the benchmark CI results in the PR (for example by editing the comment with the link like I just did). Jenkins results are not permanent.

ruyadorno pushed a commit that referenced this pull request Sep 28, 2023
@ruyadorno ruyadorno mentioned this pull request Sep 28, 2023
ruyadorno pushed a commit that referenced this pull request Sep 28, 2023
@ruyadorno ruyadorno mentioned this pull request Sep 28, 2023
alexfernandez pushed a commit to alexfernandez/node that referenced this pull request Nov 1, 2023
@richardlau richardlau added the dont-land-on-v18.x PRs that should not land on the v18.x-staging branch and should not be released in v18.x. label Mar 15, 2024
nodejs-github-bot pushed a commit that referenced this pull request Mar 18, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Vinícius Lourenço Claro Cardoso <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
rdw-msft pushed a commit to rdw-msft/node that referenced this pull request Mar 26, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: nodejs#52101
Fixes: nodejs#52079
Refs: nodejs#49691
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Vinícius Lourenço Claro Cardoso <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
marco-ippolito pushed a commit that referenced this pull request May 2, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Vinícius Lourenço Claro Cardoso <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
marco-ippolito pushed a commit that referenced this pull request May 3, 2024
Fix a file permissions regression when `fs.readFileSync()` is called in
append mode on a file that does not already exist introduced by the
fast path for utf8 encoding.

PR-URL: #52101
Fixes: #52079
Refs: #49691
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Vinícius Lourenço Claro Cardoso <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. dont-land-on-v18.x PRs that should not land on the v18.x-staging branch and should not be released in v18.x. fs Issues and PRs related to the fs subsystem / file system. needs-benchmark-ci PR that need a benchmark CI run. needs-ci PRs that need a full CI run. performance Issues and PRs related to the performance of Node.js.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants