From 1c3df965705d156db7b8132b86b3193a7467a2e2 Mon Sep 17 00:00:00 2001 From: Brian White Date: Fri, 13 Jan 2017 05:09:52 -0500 Subject: [PATCH] fs: replace regexp with function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replacing the path separator-finding regexp with a custom function results in a measurable improvement in performance. PR-URL: https://github.com/nodejs/node/pull/10789 Reviewed-By: James M Snell Reviewed-By: Michaƫl Zasso Reviewed-By: Michael Dawson Reviewed-By: Matteo Collina Reviewed-By: Benjamin Gruenbaum --- lib/fs.js | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 3e9a0540dd9..7cf96d88f18 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1478,12 +1478,6 @@ fs.unwatchFile = function(filename, listener) { }; -// Regexp that finds the next portion of a (partial) path -// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] -const nextPartRe = isWindows ? - /(.*?)(?:[/\\]+|$)/g : - /(.*?)(?:[/]+|$)/g; - // Regex to find the device root, including trailing slash. E.g. 'c:\\'. const splitRootRe = isWindows ? /^(?:[a-zA-Z]:|[\\/]{2}[^\\/]+[\\/][^\\/]+)?[\\/]*/ : @@ -1500,6 +1494,21 @@ function encodeRealpathResult(result, options) { } } +// Finds the next portion of a (partial) path, up to the next path delimiter +var nextPart; +if (isWindows) { + nextPart = function nextPart(p, i) { + for (; i < p.length; ++i) { + const ch = p.charCodeAt(i); + if (ch === 92/*'\'*/ || ch === 47/*'/'*/) + return i; + } + return -1; + }; +} else { + nextPart = function nextPart(p, i) { return p.indexOf('/', i); }; +} + fs.realpathSync = function realpathSync(p, options) { options = getOptions(options, {}); handleError((p = getPathFromURL(p))); @@ -1544,12 +1553,18 @@ fs.realpathSync = function realpathSync(p, options) { // NB: p.length changes. while (pos < p.length) { // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); + var result = nextPart(p, pos); previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; + if (result === -1) { + var last = p.slice(pos); + current += last; + base = previous + last; + pos = p.length; + } else { + current += p.slice(pos, result + 1); + base = previous + p.slice(pos, result); + pos = result + 1; + } // continue if not a symlink if (knownHard[base] || (cache && cache.get(base) === base)) { @@ -1658,12 +1673,18 @@ fs.realpath = function realpath(p, options, callback) { } // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); + var result = nextPart(p, pos); previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; + if (result === -1) { + var last = p.slice(pos); + current += last; + base = previous + last; + pos = p.length; + } else { + current += p.slice(pos, result + 1); + base = previous + p.slice(pos, result); + pos = result + 1; + } // continue if not a symlink if (knownHard[base]) {