summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-10-09 01:23:18 +0200
committerAnna Henningsen <anna@addaleax.net>2019-10-11 23:09:39 +0200
commit5c93aab278f6e09e345270b3a0fe49c591a0424f (patch)
tree7ba5931ecb38d399154e7fb1f28975eec3bb5344 /lib
parentc0305af2c4aba6d6ecd39eb100a59998d87ddc69 (diff)
downloadandroid-node-v8-5c93aab278f6e09e345270b3a0fe49c591a0424f.tar.gz
android-node-v8-5c93aab278f6e09e345270b3a0fe49c591a0424f.tar.bz2
android-node-v8-5c93aab278f6e09e345270b3a0fe49c591a0424f.zip
fs: buffer dir entries in opendir()
Read up to 32 directory entries in one batch when `dir.readSync()` or `dir.read()` are called. This increases performance significantly, although it introduces quite a bit of edge case complexity. confidence improvement accuracy (*) (**) (***) fs/bench-opendir.js mode='async' dir='lib' n=100 *** 155.93 % ±30.05% ±40.34% ±53.21% fs/bench-opendir.js mode='async' dir='test/parallel' n=100 *** 479.65 % ±56.81% ±76.47% ±101.32% fs/bench-opendir.js mode='sync' dir='lib' n=100 10.38 % ±14.39% ±19.16% ±24.96% fs/bench-opendir.js mode='sync' dir='test/parallel' n=100 *** 63.13 % ±12.84% ±17.18% ±22.58% PR-URL: https://github.com/nodejs/node/pull/29893 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/internal/fs/dir.js27
1 files changed, 26 insertions, 1 deletions
diff --git a/lib/internal/fs/dir.js b/lib/internal/fs/dir.js
index 175c632fc7..fedd7ff8ed 100644
--- a/lib/internal/fs/dir.js
+++ b/lib/internal/fs/dir.js
@@ -24,8 +24,10 @@ const {
const kDirHandle = Symbol('kDirHandle');
const kDirPath = Symbol('kDirPath');
+const kDirBufferedEntries = Symbol('kDirBufferedEntries');
const kDirClosed = Symbol('kDirClosed');
const kDirOptions = Symbol('kDirOptions');
+const kDirReadImpl = Symbol('kDirReadImpl');
const kDirReadPromisified = Symbol('kDirReadPromisified');
const kDirClosePromisified = Symbol('kDirClosePromisified');
@@ -33,6 +35,7 @@ class Dir {
constructor(handle, path, options) {
if (handle == null) throw new ERR_MISSING_ARGS('handle');
this[kDirHandle] = handle;
+ this[kDirBufferedEntries] = [];
this[kDirPath] = path;
this[kDirClosed] = false;
@@ -40,7 +43,8 @@ class Dir {
encoding: 'utf8'
});
- this[kDirReadPromisified] = internalUtil.promisify(this.read).bind(this);
+ this[kDirReadPromisified] =
+ internalUtil.promisify(this[kDirReadImpl]).bind(this, false);
this[kDirClosePromisified] = internalUtil.promisify(this.close).bind(this);
}
@@ -49,6 +53,10 @@ class Dir {
}
read(callback) {
+ return this[kDirReadImpl](true, callback);
+ }
+
+ [kDirReadImpl](maybeSync, callback) {
if (this[kDirClosed] === true) {
throw new ERR_DIR_CLOSED();
}
@@ -59,11 +67,22 @@ class Dir {
throw new ERR_INVALID_CALLBACK(callback);
}
+ if (this[kDirBufferedEntries].length > 0) {
+ const [ name, type ] = this[kDirBufferedEntries].splice(0, 2);
+ if (maybeSync)
+ process.nextTick(getDirent, this[kDirPath], name, type, callback);
+ else
+ getDirent(this[kDirPath], name, type, callback);
+ return;
+ }
+
const req = new FSReqCallback();
req.oncomplete = (err, result) => {
if (err || result === null) {
return callback(err, result);
}
+
+ this[kDirBufferedEntries] = result.slice(2);
getDirent(this[kDirPath], result[0], result[1], callback);
};
@@ -78,6 +97,11 @@ class Dir {
throw new ERR_DIR_CLOSED();
}
+ if (this[kDirBufferedEntries].length > 0) {
+ const [ name, type ] = this[kDirBufferedEntries].splice(0, 2);
+ return getDirent(this[kDirPath], name, type);
+ }
+
const ctx = { path: this[kDirPath] };
const result = this[kDirHandle].read(
this[kDirOptions].encoding,
@@ -90,6 +114,7 @@ class Dir {
return result;
}
+ this[kDirBufferedEntries] = result.slice(2);
return getDirent(this[kDirPath], result[0], result[1]);
}