From 0ae8c6db54923e5837413153a3cdb46135e110bb Mon Sep 17 00:00:00 2001 From: Mark Molinaro Date: Sun, 14 Nov 2021 13:25:35 -0800 Subject: [PATCH] perf: merge backing timestamp map for context and file dependencies --- lib/Compilation.js | 6 ----- lib/FileSystemInfo.js | 32 +++++++++++++-------------- lib/WatchIgnorePlugin.js | 39 ++++++++++++++------------------- lib/Watching.js | 37 +++++-------------------------- lib/node/NodeWatchFileSystem.js | 2 +- lib/util/fs.js | 2 +- types.d.ts | 3 ++- 7 files changed, 41 insertions(+), 80 deletions(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index efdeaa1b608..7412173fd61 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -885,12 +885,6 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si if (compiler.fileTimestamps) { this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true); } - if (compiler.contextTimestamps) { - this.fileSystemInfo.addContextTimestamps( - compiler.contextTimestamps, - true - ); - } /** @type {Map>} */ this.valueCacheVersions = new Map(); this.requestShortener = compiler.requestShortener; diff --git a/lib/FileSystemInfo.js b/lib/FileSystemInfo.js index f3337a00713..4904bcd2046 100644 --- a/lib/FileSystemInfo.js +++ b/lib/FileSystemInfo.js @@ -951,7 +951,7 @@ class FileSystemInfo { /** @type {Map} */ this._fileTshs = new Map(); /** @type {StackedCacheMap} */ - this._contextTimestamps = new StackedCacheMap(); + this._contextTimestamps = this._fileTimestamps; /** @type {Map} */ this._contextHashes = new Map(); /** @type {Map} */ @@ -1016,8 +1016,7 @@ class FileSystemInfo { this.immutablePaths.filter(p => typeof p !== "string") ); - this._cachedDeprecatedFileTimestamps = undefined; - this._cachedDeprecatedContextTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; this._warnAboutExperimentalEsmTracking = false; @@ -1152,8 +1151,7 @@ class FileSystemInfo { this._managedItems.clear(); this._managedItems.clear(); - this._cachedDeprecatedFileTimestamps = undefined; - this._cachedDeprecatedContextTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; this._statCreatedSnapshots = 0; this._statTestedSnapshotsCached = 0; @@ -1170,7 +1168,7 @@ class FileSystemInfo { */ addFileTimestamps(map, immutable) { this._fileTimestamps.addAll(map, immutable); - this._cachedDeprecatedFileTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; } /** @@ -1180,7 +1178,7 @@ class FileSystemInfo { */ addContextTimestamps(map, immutable) { this._contextTimestamps.addAll(map, immutable); - this._cachedDeprecatedContextTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; } /** @@ -2804,7 +2802,7 @@ class FileSystemInfo { if (err) { if (err.code === "ENOENT") { this._fileTimestamps.set(path, null); - this._cachedDeprecatedFileTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; return callback(null, null); } return callback(err); @@ -2828,7 +2826,7 @@ class FileSystemInfo { } this._fileTimestamps.set(path, ts); - this._cachedDeprecatedFileTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; callback(null, ts); }); @@ -3042,7 +3040,7 @@ class FileSystemInfo { }; this._fileTimestamps.set(file, ts); - this._cachedDeprecatedFileTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; callback(null, ts); }, fromDirectory: (directory, stat, callback) => { @@ -3093,7 +3091,7 @@ class FileSystemInfo { (err, result) => { if (err) return callback(err); this._contextTimestamps.set(path, result); - this._cachedDeprecatedContextTimestamps = undefined; + this._cachedDeprecatedTimestamps = undefined; callback(null, result); } @@ -3499,23 +3497,23 @@ class FileSystemInfo { } getDeprecatedFileTimestamps() { - if (this._cachedDeprecatedFileTimestamps !== undefined) - return this._cachedDeprecatedFileTimestamps; + if (this._cachedDeprecatedTimestamps !== undefined) + return this._cachedDeprecatedTimestamps; const map = new Map(); for (const [path, info] of this._fileTimestamps) { if (info) map.set(path, typeof info === "object" ? info.safeTime : null); } - return (this._cachedDeprecatedFileTimestamps = map); + return (this._cachedDeprecatedTimestamps = map); } getDeprecatedContextTimestamps() { - if (this._cachedDeprecatedContextTimestamps !== undefined) - return this._cachedDeprecatedContextTimestamps; + if (this._cachedDeprecatedTimestamps !== undefined) + return this._cachedDeprecatedTimestamps; const map = new Map(); for (const [path, info] of this._contextTimestamps) { if (info) map.set(path, typeof info === "object" ? info.safeTime : null); } - return (this._cachedDeprecatedContextTimestamps = map); + return (this._cachedDeprecatedTimestamps = map); } } diff --git a/lib/WatchIgnorePlugin.js b/lib/WatchIgnorePlugin.js index 5b5b26cd4db..75809f0feed 100644 --- a/lib/WatchIgnorePlugin.js +++ b/lib/WatchIgnorePlugin.js @@ -50,44 +50,37 @@ class IgnoringWatchFileSystem { missing, startTime, options, - (err, fileTimestamps, dirTimestamps, changedFiles, removedFiles) => { + (err, fileTimestamps, changedFiles, removedFiles) => { if (err) return callback(err); for (const path of ignoredFiles) { fileTimestamps.set(path, IGNORE_TIME_ENTRY); } for (const path of ignoredDirs) { - dirTimestamps.set(path, IGNORE_TIME_ENTRY); + fileTimestamps.set(path, IGNORE_TIME_ENTRY); } - callback( - err, - fileTimestamps, - dirTimestamps, - changedFiles, - removedFiles - ); + callback(err, fileTimestamps, changedFiles, removedFiles); }, callbackUndelayed ); + const getTimeInfoEntries = () => { + const fileTimestamps = watcher.getFileTimeInfoEntries(); + for (const path of ignoredFiles) { + fileTimestamps.set(path, IGNORE_TIME_ENTRY); + } + for (const path of ignoredDirs) { + fileTimestamps.set(path, IGNORE_TIME_ENTRY); + } + return fileTimestamps; + }; + return { close: () => watcher.close(), pause: () => watcher.pause(), - getContextTimeInfoEntries: () => { - const dirTimestamps = watcher.getContextTimeInfoEntries(); - for (const path of ignoredDirs) { - dirTimestamps.set(path, IGNORE_TIME_ENTRY); - } - return dirTimestamps; - }, - getFileTimeInfoEntries: () => { - const fileTimestamps = watcher.getFileTimeInfoEntries(); - for (const path of ignoredFiles) { - fileTimestamps.set(path, IGNORE_TIME_ENTRY); - } - return fileTimestamps; - } + getFileTimeInfoEntries: getTimeInfoEntries, + getContextTimeInfoEntries: getTimeInfoEntries }; } } diff --git a/lib/Watching.js b/lib/Watching.js index fc6c176b714..956d0f1ea1d 100644 --- a/lib/Watching.js +++ b/lib/Watching.js @@ -91,12 +91,11 @@ class Watching { /** * @param {ReadonlyMap=} fileTimeInfoEntries info for files - * @param {ReadonlyMap=} contextTimeInfoEntries info for directories * @param {ReadonlySet=} changedFiles changed files * @param {ReadonlySet=} removedFiles removed files * @returns {void} */ - _go(fileTimeInfoEntries, contextTimeInfoEntries, changedFiles, removedFiles) { + _go(fileTimeInfoEntries, changedFiles, removedFiles) { this._initial = false; if (this.startTime === null) this.startTime = Date.now(); this.running = true; @@ -126,12 +125,9 @@ class Watching { this.compiler.removedFiles = this._collectedRemovedFiles; this._collectedRemovedFiles = undefined; - this.compiler.fileTimestamps = + this.compiler.fileTimestamps = this.compiler.contextTimestamps = fileTimeInfoEntries || (this.pausedWatcher && this.pausedWatcher.getFileTimeInfoEntries()); - this.compiler.contextTimestamps = - contextTimeInfoEntries || - (this.pausedWatcher && this.pausedWatcher.getContextTimeInfoEntries()); const run = () => { if (this.compiler.idle) { @@ -314,13 +310,7 @@ class Watching { missing, this.lastWatcherStartTime, this.watchOptions, - ( - err, - fileTimeInfoEntries, - contextTimeInfoEntries, - changedFiles, - removedFiles - ) => { + (err, fileTimeInfoEntries, changedFiles, removedFiles) => { if (err) { this.compiler.modifiedFiles = undefined; this.compiler.removedFiles = undefined; @@ -329,12 +319,7 @@ class Watching { this.compiler.fsStartTime = undefined; return this.handler(err); } - this._invalidate( - fileTimeInfoEntries, - contextTimeInfoEntries, - changedFiles, - removedFiles - ); + this._invalidate(fileTimeInfoEntries, changedFiles, removedFiles); this._onChange(); }, (fileName, changeTime) => { @@ -363,12 +348,7 @@ class Watching { this._invalidate(); } - _invalidate( - fileTimeInfoEntries, - contextTimeInfoEntries, - changedFiles, - removedFiles - ) { + _invalidate(fileTimeInfoEntries, changedFiles, removedFiles) { if (this.suspended || (this._isBlocked() && (this.blocked = true))) { this._mergeWithCollected(changedFiles, removedFiles); return; @@ -378,12 +358,7 @@ class Watching { this._mergeWithCollected(changedFiles, removedFiles); this.invalid = true; } else { - this._go( - fileTimeInfoEntries, - contextTimeInfoEntries, - changedFiles, - removedFiles - ); + this._go(fileTimeInfoEntries, changedFiles, removedFiles); } } diff --git a/lib/node/NodeWatchFileSystem.js b/lib/node/NodeWatchFileSystem.js index 67ef918b8a3..66526437874 100644 --- a/lib/node/NodeWatchFileSystem.js +++ b/lib/node/NodeWatchFileSystem.js @@ -79,7 +79,7 @@ class NodeWatchFileSystem { } } const times = this.watcher.getTimeInfoEntries(); - callback(null, times, times, changes, removals); + callback(null, times, changes, removals); }); this.watcher.watch({ files, directories, missing, startTime }); diff --git a/lib/util/fs.js b/lib/util/fs.js index 9ba425c0621..0efca048fda 100644 --- a/lib/util/fs.js +++ b/lib/util/fs.js @@ -68,7 +68,7 @@ const path = require("path"); * @property {function(): Set=} getAggregatedChanges get current aggregated changes that have not yet send to callback * @property {function(): Set=} getAggregatedRemovals get current aggregated removals that have not yet send to callback * @property {function(): Map} getFileTimeInfoEntries get info about files - * @property {function(): Map} getContextTimeInfoEntries get info about directories + * @property {function(): Map} getContextTimeInfoEntries deprecated - use getFileTimeInfoEntries instead (TODO remove in webpack 6). */ /** diff --git a/types.d.ts b/types.d.ts index a6468b57877..126ec37d92d 100644 --- a/types.d.ts +++ b/types.d.ts @@ -6260,6 +6260,7 @@ declare interface LoaderRunnerLoaderContext { /** * An array of all the loaders. It is writeable in the pitch phase. * loaders = [{request: string, path: string, query: string, module: function}] + * * In the example: * [ * { request: "/abc/loader1.js?xyz", @@ -11734,7 +11735,7 @@ declare interface Watcher { getFileTimeInfoEntries: () => Map; /** - * get info about directories + * deprecated - use getFileTimeInfoEntries instead (TODO remove in webpack 6). */ getContextTimeInfoEntries: () => Map; }