Skip to content

Commit 8f8be72

Browse files
author
pluris
committed
fs: improve error performance for writeSync
1 parent 6a1abd2 commit 8f8be72

File tree

5 files changed

+79
-29
lines changed

5 files changed

+79
-29
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-7
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ const {
107107
getValidatedFd,
108108
getValidatedPath,
109109
getValidMode,
110-
handleErrorFromBinding,
111110
possiblyTransformPath,
112111
preprocessSymlinkDestination,
113112
Stats,
@@ -898,7 +897,6 @@ ObjectDefineProperty(write, kCustomPromisifyArgsSymbol,
898897
*/
899898
function writeSync(fd, buffer, offsetOrOptions, length, position) {
900899
fd = getValidatedFd(fd);
901-
const ctx = {};
902900
let result;
903901

904902
let offset = offsetOrOptions;
@@ -920,18 +918,15 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) {
920918
if (typeof length !== 'number')
921919
length = buffer.byteLength - offset;
922920
validateOffsetLengthWrite(offset, length, buffer.byteLength);
923-
result = binding.writeBuffer(fd, buffer, offset, length, position,
924-
undefined, ctx);
921+
result = binding.writeBuffer(fd, buffer, offset, length, position);
925922
} else {
926923
validateStringAfterArrayBufferView(buffer, 'buffer');
927924
validateEncoding(buffer, length);
928925

929926
if (offset === undefined)
930927
offset = null;
931-
result = binding.writeString(fd, buffer, offset, length,
932-
undefined, ctx);
928+
result = binding.writeString(fd, buffer, offset, length);
933929
}
934-
handleErrorFromBinding(ctx);
935930
return result;
936931
}
937932

lib/internal/net.js

+4-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const {
88

99
const Buffer = require('buffer').Buffer;
1010
const { writeBuffer } = internalBinding('fs');
11-
const errors = require('internal/errors');
1211

1312
// IPv4 Segment
1413
const v4Seg = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])';
@@ -55,12 +54,10 @@ function makeSyncWrite(fd) {
5554

5655
this._handle.bytesWritten += chunk.length;
5756

58-
const ctx = {};
59-
writeBuffer(fd, chunk, 0, chunk.length, null, undefined, ctx);
60-
if (ctx.errno !== undefined) {
61-
const ex = new errors.UVException(ctx);
62-
ex.errno = ctx.errno;
63-
return cb(ex);
57+
try {
58+
writeBuffer(fd, chunk, 0, chunk.length, null);
59+
} catch (e) {
60+
return cb(e);
6461
}
6562
cb();
6663
};

src/node_file.cc

+17-13
Original file line numberDiff line numberDiff line change
@@ -2030,7 +2030,7 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20302030
Environment* env = Environment::GetCurrent(args);
20312031

20322032
const int argc = args.Length();
2033-
CHECK_GE(argc, 4);
2033+
CHECK_GE(argc, 5);
20342034

20352035
CHECK(args[0]->IsInt32());
20362036
const int fd = args[0].As<Int32>()->Value();
@@ -2057,18 +2057,20 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20572057
char* buf = buffer_data + off;
20582058
uv_buf_t uvbuf = uv_buf_init(buf, len);
20592059

2060-
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
2061-
if (req_wrap_async != nullptr) { // write(fd, buffer, off, len, pos, req)
2060+
if (argc > 5) { // write(fd, buffer, off, len, pos, req)
2061+
FSReqBase* req_wrap_async = GetReqWrap(args, 5);
20622062
FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
20632063
AsyncCall(env, req_wrap_async, args, "write", UTF8, AfterInteger,
20642064
uv_fs_write, fd, &uvbuf, 1, pos);
2065-
} else { // write(fd, buffer, off, len, pos, undefined, ctx)
2066-
CHECK_EQ(argc, 7);
2067-
FSReqWrapSync req_wrap_sync;
2065+
} else { // write(fd, buffer, off, len, pos)
2066+
FSReqWrapSync req_wrap_sync("write");
20682067
FS_SYNC_TRACE_BEGIN(write);
2069-
int bytesWritten = SyncCall(env, args[6], &req_wrap_sync, "write",
2070-
uv_fs_write, fd, &uvbuf, 1, pos);
2068+
int bytesWritten = SyncCallAndThrowOnError(
2069+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
20712070
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2071+
if (is_uv_error(bytesWritten)) {
2072+
return;
2073+
}
20722074
args.GetReturnValue().Set(bytesWritten);
20732075
}
20742076
}
@@ -2205,9 +2207,8 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22052207
} else {
22062208
req_wrap_async->SetReturnValue(args);
22072209
}
2208-
} else { // write(fd, string, pos, enc, undefined, ctx)
2209-
CHECK_EQ(argc, 6);
2210-
FSReqWrapSync req_wrap_sync;
2210+
} else { // write(fd, string, pos, enc)
2211+
FSReqWrapSync req_wrap_sync("write");
22112212
FSReqBase::FSReqBuffer stack_buffer;
22122213
if (buf == nullptr) {
22132214
if (!StringBytes::StorageSize(isolate, value, enc).To(&len))
@@ -2222,9 +2223,12 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
22222223
}
22232224
uv_buf_t uvbuf = uv_buf_init(buf, len);
22242225
FS_SYNC_TRACE_BEGIN(write);
2225-
int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write",
2226-
uv_fs_write, fd, &uvbuf, 1, pos);
2226+
int bytesWritten = SyncCallAndThrowOnError(
2227+
env, &req_wrap_sync, uv_fs_write, fd, &uvbuf, 1, pos);
22272228
FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
2229+
if (is_uv_error(bytesWritten)) {
2230+
return;
2231+
}
22282232
args.GetReturnValue().Set(bytesWritten);
22292233
}
22302234
}

typings/internalBinding/fs.d.ts

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

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

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

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

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

0 commit comments

Comments
 (0)