Skip to content

Commit e742422

Browse files
trevnorrisFishrock123
authored andcommitted
fs: use pushValueToArray for readdir(Sync)
Improve performance by pushing directory entries to returned array in batches of 8 using pushValueToArray() in JS. Add benchmarks to demonstrate this improvement. PR-URL: nodejs#3780 Reviewed-By: Fedor Indutny <[email protected]>
1 parent b8366e7 commit e742422

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

benchmark/fs/bench-readdir.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
6+
const bench = common.createBenchmark(main, {
7+
n: [1e4],
8+
});
9+
10+
11+
function main(conf) {
12+
const n = conf.n >>> 0;
13+
14+
bench.start();
15+
(function r(cntr) {
16+
if (--cntr <= 0)
17+
return bench.end(n);
18+
fs.readdir(__dirname + '/../../lib/', function() {
19+
r(cntr);
20+
});
21+
}(n));
22+
}

benchmark/fs/bench-readdirSync.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
6+
const bench = common.createBenchmark(main, {
7+
n: [1e4],
8+
});
9+
10+
11+
function main(conf) {
12+
const n = conf.n >>> 0;
13+
14+
bench.start();
15+
for (var i = 0; i < n; i++) {
16+
fs.readdirSync(__dirname + '/../../lib/');
17+
}
18+
bench.end(n);
19+
}

src/node_file.cc

+31-6
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ static void After(uv_fs_t *req) {
214214
{
215215
int r;
216216
Local<Array> names = Array::New(env->isolate(), 0);
217+
Local<Function> fn = env->push_values_to_array_function();
218+
Local<Value> name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
219+
size_t name_idx = 0;
217220

218221
for (int i = 0; ; i++) {
219222
uv_dirent_t ent;
@@ -229,9 +232,19 @@ static void After(uv_fs_t *req) {
229232
break;
230233
}
231234

232-
Local<String> name = String::NewFromUtf8(env->isolate(),
233-
ent.name);
234-
names->Set(i, name);
235+
name_argv[name_idx++] =
236+
String::NewFromUtf8(env->isolate(), ent.name);
237+
238+
if (name_idx >= ARRAY_SIZE(name_argv)) {
239+
fn->Call(env->context(), names, name_idx, name_argv)
240+
.ToLocalChecked();
241+
name_idx = 0;
242+
}
243+
}
244+
245+
if (name_idx > 0) {
246+
fn->Call(env->context(), names, name_idx, name_argv)
247+
.ToLocalChecked();
235248
}
236249

237250
argv[1] = names;
@@ -811,6 +824,9 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
811824
CHECK_GE(SYNC_REQ.result, 0);
812825
int r;
813826
Local<Array> names = Array::New(env->isolate(), 0);
827+
Local<Function> fn = env->push_values_to_array_function();
828+
Local<Value> name_v[NODE_PUSH_VAL_TO_ARRAY_MAX];
829+
size_t name_idx = 0;
814830

815831
for (int i = 0; ; i++) {
816832
uv_dirent_t ent;
@@ -821,9 +837,18 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
821837
if (r != 0)
822838
return env->ThrowUVException(r, "readdir", "", *path);
823839

824-
Local<String> name = String::NewFromUtf8(env->isolate(),
825-
ent.name);
826-
names->Set(i, name);
840+
841+
name_v[name_idx++] = String::NewFromUtf8(env->isolate(), ent.name);
842+
843+
if (name_idx >= ARRAY_SIZE(name_v)) {
844+
fn->Call(env->context(), names, name_idx, name_v)
845+
.ToLocalChecked();
846+
name_idx = 0;
847+
}
848+
}
849+
850+
if (name_idx > 0) {
851+
fn->Call(env->context(), names, name_idx, name_v).ToLocalChecked();
827852
}
828853

829854
args.GetReturnValue().Set(names);

0 commit comments

Comments
 (0)