From d4a6f2caf13634f00b4389f1069f19de0b15551b Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Fri, 31 Dec 2021 15:22:56 -0500 Subject: [PATCH] fs: use async directory processing in cp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readdir() functions do not scale well, which is why opendir(), etc. were introduced. This is exacerbated in the current cp() implementation, which calls readdir() recursively. This commit updates cp() to use the opendir() style iteration. PR-URL: https://github.com/nodejs/node/pull/41351 Reviewed-By: Luigi Pinca Reviewed-By: Tierney Cyren Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Juan José Arboleda Reviewed-By: Mohammed Keyvanzadeh --- lib/internal/fs/cp/cp-sync.js | 24 ++++++++++++++++-------- lib/internal/fs/cp/cp.js | 12 ++++++------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/internal/fs/cp/cp-sync.js b/lib/internal/fs/cp/cp-sync.js index 3ee6a70f959582..497c8c57c317dd 100644 --- a/lib/internal/fs/cp/cp-sync.js +++ b/lib/internal/fs/cp/cp-sync.js @@ -32,7 +32,7 @@ const { existsSync, lstatSync, mkdirSync, - readdirSync, + opendirSync, readlinkSync, statSync, symlinkSync, @@ -275,14 +275,22 @@ function mkDirAndCopy(srcMode, src, dest, opts) { } function copyDir(src, dest, opts) { - readdirSync(src).forEach((item) => copyDirItem(item, src, dest, opts)); -} + const dir = opendirSync(src); + + try { + let dirent; -function copyDirItem(item, src, dest, opts) { - const srcItem = join(src, item); - const destItem = join(dest, item); - const { destStat } = checkPathsSync(srcItem, destItem, opts); - return startCopy(destStat, srcItem, destItem, opts); + while ((dirent = dir.readSync()) !== null) { + const { name } = dirent; + const srcItem = join(src, name); + const destItem = join(dest, name); + const { destStat } = checkPathsSync(srcItem, destItem, opts); + + startCopy(destStat, srcItem, destItem, opts); + } + } finally { + dir.closeSync(); + } } function onLink(destStat, src, dest) { diff --git a/lib/internal/fs/cp/cp.js b/lib/internal/fs/cp/cp.js index 090a4023df14e8..6dc212f2f6a5fc 100644 --- a/lib/internal/fs/cp/cp.js +++ b/lib/internal/fs/cp/cp.js @@ -41,7 +41,7 @@ const { copyFile, lstat, mkdir, - readdir, + opendir, readlink, stat, symlink, @@ -325,11 +325,11 @@ async function mkDirAndCopy(srcMode, src, dest, opts) { } async function copyDir(src, dest, opts) { - const dir = await readdir(src); - for (let i = 0; i < dir.length; i++) { - const item = dir[i]; - const srcItem = join(src, item); - const destItem = join(dest, item); + const dir = await opendir(src); + + for await (const { name } of dir) { + const srcItem = join(src, name); + const destItem = join(dest, name); const { destStat } = await checkPaths(srcItem, destItem, opts); await startCopy(destStat, srcItem, destItem, opts); }