Skip to content

Commit 352378a

Browse files
committed
fs: improve error performance of fs.writeSync
1 parent f8c27e6 commit 352378a

File tree

4 files changed

+73
-18
lines changed

4 files changed

+73
-18
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
const tmpdir = require('../../test/common/tmpdir');
6+
tmpdir.refresh();
7+
8+
const bench = common.createBenchmark(main, {
9+
n: [1e4],
10+
});
11+
12+
function main({ n, type }) {
13+
const path = tmpdir.resolve(`new-file-${process.pid}`);
14+
15+
bench.start();
16+
for (let i = 0; i < n; i++) {
17+
fs.writeFileSync(path, 'Benchmark data.');
18+
}
19+
bench.end(n);
20+
}

benchmark/fs/bench-writeSync.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
const tmpdir = require('../../test/common/tmpdir');
6+
tmpdir.refresh();
7+
8+
const path = tmpdir.resolve(`new-file-${process.pid}`);
9+
fs.writeFileSync(path, 'Some content.');
10+
11+
const bench = common.createBenchmark(main, {
12+
type: ['valid', 'invalid'],
13+
dataType: ['string', 'buffer'],
14+
n: [1e5],
15+
});
16+
17+
const stringData = 'Benchmark data.';
18+
const bufferData = Buffer.from(stringData);
19+
20+
function main({ n, type, dataType }) {
21+
const fd = type === 'valid' ? fs.openSync(path, 'r+') : 1 << 30;
22+
const data = dataType === 'string' ? stringData : bufferData;
23+
24+
bench.start();
25+
for (let i = 0; i < n; i++) {
26+
try {
27+
fs.writeSync(fd, data);
28+
} catch {
29+
// Continue regardless of error.
30+
}
31+
}
32+
bench.end(n);
33+
if (type === 'valid') fs.closeSync(fd);
34+
}

lib/fs.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -922,18 +922,15 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) {
922922
if (typeof length !== 'number')
923923
length = buffer.byteLength - offset;
924924
validateOffsetLengthWrite(offset, length, buffer.byteLength);
925-
result = binding.writeBuffer(fd, buffer, offset, length, position,
926-
undefined, ctx);
925+
result = binding.writeBuffer(fd, buffer, offset, length, position);
927926
} else {
928927
validateStringAfterArrayBufferView(buffer, 'buffer');
929928
validateEncoding(buffer, length);
930929

931930
if (offset === undefined)
932931
offset = null;
933-
result = binding.writeString(fd, buffer, offset, length,
934-
undefined, ctx);
932+
result = binding.writeString(fd, buffer, offset, length);
935933
}
936-
handleErrorFromBinding(ctx);
937934
return result;
938935
}
939936

src/node_file.cc

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,7 +2033,7 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20332033
Environment* env = Environment::GetCurrent(args);
20342034

20352035
const int argc = args.Length();
2036-
CHECK_GE(argc, 4);
2036+
CHECK_GE(argc, 5);
20372037

20382038
CHECK(args[0]->IsInt32());
20392039
const int fd = args[0].As<Int32>()->Value();
@@ -2060,18 +2060,20 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20602060
char* buf = buffer_data + off;
20612061
uv_buf_t uvbuf = uv_buf_init(buf, len);
20622062

2063-
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
2064-
if (req_wrap_async != nullptr) { // write(fd, buffer, off, len, pos, req)
2063+
if (argc > 5) { // write(fd, buffer, off, len, pos, req)
2064+
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
20652065
FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
20662066
AsyncCall(env, req_wrap_async, args, "write", UTF8, AfterInteger,
20672067
uv_fs_write, fd, &uvbuf, 1, pos);
2068-
} else { // write(fd, buffer, off, len, pos, undefined, ctx)
2069-
CHECK_EQ(argc, 7);
2070-
FSReqWrapSync req_wrap_sync;
2068+
} else { // write(fd, buffer, off, len, pos)
2069+
FSReqWrapSync req_wrap_sync("write");
20712070
FS_SYNC_TRACE_BEGIN(write);
2072-
int bytesWritten = SyncCall(env, args[6], &req_wrap_sync, "write",
2073-
uv_fs_write, fd, &uvbuf, 1, pos);
2071+
int bytesWritten = SyncCallAndThrowOnError(
2072+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
20742073
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2074+
if (is_uv_error(bytesWritten)) {
2075+
return;
2076+
}
20752077
args.GetReturnValue().Set(bytesWritten);
20762078
}
20772079
}
@@ -2208,9 +2210,8 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22082210
} else {
22092211
req_wrap_async->SetReturnValue(args);
22102212
}
2211-
} else { // write(fd, string, pos, enc, undefined, ctx)
2212-
CHECK_EQ(argc, 6);
2213-
FSReqWrapSync req_wrap_sync;
2213+
} else { // write(fd, string, pos, enc)
2214+
FSReqWrapSync req_wrap_sync("write");
22142215
FSReqBase::FSReqBuffer stack_buffer;
22152216
if (buf == nullptr) {
22162217
if (!StringBytes::StorageSize(isolate, value, enc).To(&len))
@@ -2225,9 +2226,12 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22252226
}
22262227
uv_buf_t uvbuf = uv_buf_init(buf, len);
22272228
FS_SYNC_TRACE_BEGIN(write);
2228-
int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write",
2229-
uv_fs_write, fd, &uvbuf, 1, pos);
2229+
int bytesWritten = SyncCallAndThrowOnError(
2230+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
22302231
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2232+
if (is_uv_error(bytesWritten)) {
2233+
return;
2234+
}
22312235
args.GetReturnValue().Set(bytesWritten);
22322236
}
22332237
}

0 commit comments

Comments
 (0)