Skip to content

Commit 9dba771

Browse files
anonrigtargos
authored andcommitted
fs: improve error performance of linkSync
PR-URL: #49962 Refs: nodejs/performance#106 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
1 parent ea7902d commit 9dba771

File tree

4 files changed

+60
-13
lines changed

4 files changed

+60
-13
lines changed

benchmark/fs/bench-linkSync.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
const assert = require('assert');
6+
const tmpdir = require('../../test/common/tmpdir');
7+
8+
tmpdir.refresh();
9+
const tmpfile = tmpdir.resolve(`.bench-file-data-${Date.now()}`);
10+
fs.writeFileSync(tmpfile, 'bench-file', 'utf-8');
11+
12+
const bench = common.createBenchmark(main, {
13+
type: ['valid', 'invalid'],
14+
n: [1e3],
15+
});
16+
17+
function main({ n, type }) {
18+
switch (type) {
19+
case 'valid': {
20+
bench.start();
21+
for (let i = 0; i < n; i++) {
22+
fs.linkSync(tmpfile, tmpdir.resolve(`.valid-${i}`), 'file');
23+
}
24+
bench.end(n);
25+
26+
break;
27+
}
28+
29+
case 'invalid': {
30+
let hasError = false;
31+
bench.start();
32+
for (let i = 0; i < n; i++) {
33+
try {
34+
fs.linkSync(
35+
tmpdir.resolve(`.non-existing-file-for-linkSync-${i}`),
36+
__filename,
37+
'file',
38+
);
39+
} catch {
40+
hasError = true;
41+
}
42+
}
43+
bench.end(n);
44+
assert(hasError);
45+
break;
46+
}
47+
default:
48+
new Error('Invalid type');
49+
}
50+
}

lib/fs.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -1845,12 +1845,10 @@ function linkSync(existingPath, newPath) {
18451845
existingPath = getValidatedPath(existingPath, 'existingPath');
18461846
newPath = getValidatedPath(newPath, 'newPath');
18471847

1848-
const ctx = { path: existingPath, dest: newPath };
1849-
const result = binding.link(pathModule.toNamespacedPath(existingPath),
1850-
pathModule.toNamespacedPath(newPath),
1851-
undefined, ctx);
1852-
handleErrorFromBinding(ctx);
1853-
return result;
1848+
binding.link(
1849+
pathModule.toNamespacedPath(existingPath),
1850+
pathModule.toNamespacedPath(newPath),
1851+
);
18541852
}
18551853

18561854
/**

src/node_file.cc

+5-7
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ static void Link(const FunctionCallbackInfo<Value>& args) {
13771377
Isolate* isolate = env->isolate();
13781378

13791379
const int argc = args.Length();
1380-
CHECK_GE(argc, 3);
1380+
CHECK_GE(argc, 2);
13811381

13821382
BufferValue src(isolate, args[0]);
13831383
CHECK_NOT_NULL(*src);
@@ -1395,8 +1395,8 @@ static void Link(const FunctionCallbackInfo<Value>& args) {
13951395
THROW_IF_INSUFFICIENT_PERMISSIONS(
13961396
env, permission::PermissionScope::kFileSystemWrite, dest_view);
13971397

1398-
FSReqBase* req_wrap_async = GetReqWrap(args, 2);
1399-
if (req_wrap_async != nullptr) { // link(src, dest, req)
1398+
if (argc > 2) { // link(src, dest, req)
1399+
FSReqBase* req_wrap_async = GetReqWrap(args, 2);
14001400
FS_ASYNC_TRACE_BEGIN2(UV_FS_LINK,
14011401
req_wrap_async,
14021402
"src",
@@ -1406,11 +1406,9 @@ static void Link(const FunctionCallbackInfo<Value>& args) {
14061406
AsyncDestCall(env, req_wrap_async, args, "link", *dest, dest.length(), UTF8,
14071407
AfterNoArgs, uv_fs_link, *src, *dest);
14081408
} else { // link(src, dest)
1409-
CHECK_EQ(argc, 4);
1410-
FSReqWrapSync req_wrap_sync;
1409+
FSReqWrapSync req_wrap_sync("link", *src, *dest);
14111410
FS_SYNC_TRACE_BEGIN(link);
1412-
SyncCall(env, args[3], &req_wrap_sync, "link",
1413-
uv_fs_link, *src, *dest);
1411+
SyncCallAndThrowOnError(env, &req_wrap_sync, uv_fs_link, *src, *dest);
14141412
FS_SYNC_TRACE_END(link);
14151413
}
14161414
}

typings/internalBinding/fs.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ declare namespace InternalFSBinding {
121121
function link(existingPath: string, newPath: string, req: FSReqCallback): void;
122122
function link(existingPath: string, newPath: string, req: undefined, ctx: FSSyncContext): void;
123123
function link(existingPath: string, newPath: string, usePromises: typeof kUsePromises): Promise<void>;
124+
function link(existingPath: string, newPath: string): void;
124125

125126
function lstat(path: StringOrBuffer, useBigint: boolean, req: FSReqCallback<Float64Array | BigUint64Array>): void;
126127
function lstat(path: StringOrBuffer, useBigint: true, req: FSReqCallback<BigUint64Array>): void;

0 commit comments

Comments
 (0)