From fd0a9546c44b592ceaa98692f034079b3f8e28ee Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Fri, 21 Oct 2022 19:46:13 -0400 Subject: [PATCH] fs: replace traverse with readdir for performance --- lib/internal/fs/linux_watcher.js | 40 +++++++++++--------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/lib/internal/fs/linux_watcher.js b/lib/internal/fs/linux_watcher.js index 2ee732b5f9d563..1e08dd859135b3 100644 --- a/lib/internal/fs/linux_watcher.js +++ b/lib/internal/fs/linux_watcher.js @@ -6,6 +6,7 @@ const { SafeMap, Symbol, StringPrototypeStartsWith } = primordials; const { validateObject } = require('internal/validators'); const { kEmptyObject } = require('internal/util'); const { ERR_FEATURE_UNAVAILABLE_ON_PLATFORM } = require('internal/errors'); +const { Dirent, UV_DIRENT_DIR } = require('internal/fs/utils'); const kFSWatchStart = Symbol('kFSWatchStart'); @@ -22,35 +23,20 @@ function lazyLoadFsSync() { return internalSync; } -async function traverse(dir, files = new SafeMap()) { - const { stat, opendir } = lazyLoadFsPromises(); +function traverse(dir, files = new SafeMap()) { + const { readdirSync } = lazyLoadFsSync() - files.set(dir, await stat(dir)); + const filenames = readdirSync(dir, { withFileTypes: true }); - try { - const directory = await opendir(dir); + files.set(dir, new Dirent(dir, UV_DIRENT_DIR)); - for await (const file of directory) { - const f = path.join(dir, file.name); + for (let file of filenames) { + const f = path.join(dir, file.name); - try { - const stats = await stat(f); + files.set(f, file); - files.set(f, stats); - - if (stats.isDirectory()) { - await traverse(f, files); - } - } catch (error) { - if (error.code !== 'ENOENT' || error.code !== 'EPERM') { - this.emit('error', error); - } - } - - } - } catch (error) { - if (error.code !== 'EACCES') { - this.emit('error', error); + if (file.isDirectory()) { + traverse(f, files); } } @@ -154,7 +140,7 @@ class FSWatcher extends EventEmitter { persistent: this.#options.persistent, }, (statWatcher, previousStatWatcher) => { if (existingStat && !existingStat.isDirectory() && - statWatcher.nlink !== 0 && existingStat.mtime.getTime() === statWatcher.mtime.getTime()) { + statWatcher.nlink !== 0 && existingStat.mtime?.getTime() === statWatcher.mtime?.getTime()) { return; } @@ -180,10 +166,10 @@ class FSWatcher extends EventEmitter { /** * @param {string | Buffer | URL} filename */ - async [kFSWatchStart](filename) { + [kFSWatchStart](filename) { this.#rootPath = filename; this.#closed = false; - this.#files = await traverse(filename); + this.#files = traverse(filename); for (const f of this.#files.keys()) { this.#watchFile(f);