Skip to content

Commit ee0ddb7

Browse files
author
pluris
committed
fs: improve error performance for writeSync
1 parent 52fcf14 commit ee0ddb7

File tree

4 files changed

+81
-21
lines changed

4 files changed

+81
-21
lines changed

benchmark/fs/bench-writeSync.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
tmpdir.refresh();
8+
9+
const path = tmpdir.resolve(`new-file-${process.pid}`);
10+
const parameters = [Buffer.from('Benchmark data'),
11+
0,
12+
Buffer.byteLength('Benchmark data')];
13+
const bench = common.createBenchmark(main, {
14+
type: ['valid', 'invalid'],
15+
n: [1e5],
16+
});
17+
18+
function main({ n, type }) {
19+
let fd;
20+
let result;
21+
22+
switch (type) {
23+
case 'valid':
24+
fd = fs.openSync(path, 'w');
25+
26+
bench.start();
27+
for (let i = 0; i < n; i++) {
28+
result = fs.writeSync(fd, ...parameters);
29+
}
30+
31+
bench.end(n);
32+
assert(result);
33+
fs.closeSync(fd);
34+
break;
35+
case 'invalid': {
36+
fd = 1 << 30;
37+
let hasError = false;
38+
bench.start();
39+
for (let i = 0; i < n; i++) {
40+
try {
41+
result = fs.writeSync(fd, ...parameters);
42+
} catch {
43+
hasError = true;
44+
}
45+
}
46+
47+
bench.end(n);
48+
assert(hasError);
49+
break;
50+
}
51+
default:
52+
throw new Error('Invalid type');
53+
}
54+
}

lib/fs.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,6 @@ ObjectDefineProperty(write, kCustomPromisifyArgsSymbol,
899899
*/
900900
function writeSync(fd, buffer, offsetOrOptions, length, position) {
901901
fd = getValidatedFd(fd);
902-
const ctx = {};
903902
let result;
904903

905904
let offset = offsetOrOptions;
@@ -921,18 +920,15 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) {
921920
if (typeof length !== 'number')
922921
length = buffer.byteLength - offset;
923922
validateOffsetLengthWrite(offset, length, buffer.byteLength);
924-
result = binding.writeBuffer(fd, buffer, offset, length, position,
925-
undefined, ctx);
923+
result = binding.writeBuffer(fd, buffer, offset, length, position);
926924
} else {
927925
validateStringAfterArrayBufferView(buffer, 'buffer');
928926
validateEncoding(buffer, length);
929927

930928
if (offset === undefined)
931929
offset = null;
932-
result = binding.writeString(fd, buffer, offset, length,
933-
undefined, ctx);
930+
result = binding.writeString(fd, buffer, offset, length);
934931
}
935-
handleErrorFromBinding(ctx);
936932
return result;
937933
}
938934

src/node_file.cc

+23-13
Original file line numberDiff line numberDiff line change
@@ -2098,7 +2098,7 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20982098
Environment* env = Environment::GetCurrent(args);
20992099

21002100
const int argc = args.Length();
2101-
CHECK_GE(argc, 4);
2101+
CHECK_GE(argc, 5);
21022102

21032103
CHECK(args[0]->IsInt32());
21042104
const int fd = args[0].As<Int32>()->Value();
@@ -2125,18 +2125,23 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
21252125
char* buf = buffer_data + off;
21262126
uv_buf_t uvbuf = uv_buf_init(buf, len);
21272127

2128-
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
2129-
if (req_wrap_async != nullptr) { // write(fd, buffer, off, len, pos, req)
2128+
if (argc > 5) { // write(fd, buffer, off, len, pos, req)
2129+
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
2130+
CHECK_NOT_NULL(req_wrap_async);
21302131
FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
21312132
AsyncCall(env, req_wrap_async, args, "write", UTF8, AfterInteger,
21322133
uv_fs_write, fd, &uvbuf, 1, pos);
2133-
} else { // write(fd, buffer, off, len, pos, undefined, ctx)
2134-
CHECK_EQ(argc, 7);
2135-
FSReqWrapSync req_wrap_sync;
2134+
} else { // write(fd, buffer, off, len, pos)
2135+
FSReqWrapSync req_wrap_sync("write");
21362136
FS_SYNC_TRACE_BEGIN(write);
2137-
int bytesWritten = SyncCall(env, args[6], &req_wrap_sync, "write",
2138-
uv_fs_write, fd, &uvbuf, 1, pos);
2137+
int bytesWritten = SyncCallAndThrowOnError(
2138+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
21392139
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2140+
2141+
if (is_uv_error(bytesWritten)) {
2142+
return;
2143+
}
2144+
21402145
args.GetReturnValue().Set(bytesWritten);
21412146
}
21422147
}
@@ -2273,9 +2278,9 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22732278
} else {
22742279
req_wrap_async->SetReturnValue(args);
22752280
}
2276-
} else { // write(fd, string, pos, enc, undefined, ctx)
2277-
CHECK_EQ(argc, 6);
2278-
FSReqWrapSync req_wrap_sync;
2281+
} else { // write(fd, string, pos, enc)
2282+
CHECK_EQ(argc, 4);
2283+
FSReqWrapSync req_wrap_sync("write");
22792284
FSReqBase::FSReqBuffer stack_buffer;
22802285
if (buf == nullptr) {
22812286
if (!StringBytes::StorageSize(isolate, value, enc).To(&len))
@@ -2290,9 +2295,14 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22902295
}
22912296
uv_buf_t uvbuf = uv_buf_init(buf, len);
22922297
FS_SYNC_TRACE_BEGIN(write);
2293-
int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write",
2294-
uv_fs_write, fd, &uvbuf, 1, pos);
2298+
int bytesWritten = SyncCallAndThrowOnError(
2299+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
22952300
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2301+
2302+
if (is_uv_error(bytesWritten)) {
2303+
return;
2304+
}
2305+
22962306
args.GetReturnValue().Set(bytesWritten);
22972307
}
22982308
}

typings/internalBinding/fs.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,15 @@ declare namespace InternalFSBinding {
219219
function utimes(path: string, atime: number, mtime: number, usePromises: typeof kUsePromises): Promise<void>;
220220

221221
function writeBuffer(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number | null, req: FSReqCallback<number>): void;
222-
function writeBuffer(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number | null, req: undefined, ctx: FSSyncContext): number;
222+
function writeBuffer(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number | null): number;
223223
function writeBuffer(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number | null, usePromises: typeof kUsePromises): Promise<number>;
224224

225225
function writeBuffers(fd: number, buffers: ArrayBufferView[], position: number, req: FSReqCallback<number>): void;
226226
function writeBuffers(fd: number, buffers: ArrayBufferView[], position: number, req: undefined, ctx: FSSyncContext): number;
227227
function writeBuffers(fd: number, buffers: ArrayBufferView[], position: number, usePromises: typeof kUsePromises): Promise<number>;
228228

229229
function writeString(fd: number, value: string, pos: unknown, encoding: unknown, req: FSReqCallback<number>): void;
230-
function writeString(fd: number, value: string, pos: unknown, encoding: unknown, req: undefined, ctx: FSSyncContext): number;
230+
function writeString(fd: number, value: string, pos: unknown, encoding: unknown): number;
231231
function writeString(fd: number, value: string, pos: unknown, encoding: unknown, usePromises: typeof kUsePromises): Promise<number>;
232232

233233
function getFormatOfExtensionlessFile(url: string): ConstantsBinding['fs'];

0 commit comments

Comments
 (0)