From 522d80f33b386489b6283822337428dffa0dcc86 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 29 Jan 2020 10:28:33 +0100 Subject: [PATCH] allocate less for empty Sets for runtime requirements and file/context/missingDependencies --- lib/ChunkGraph.js | 45 ++++++++++++++++++++++++++++++------------ lib/Compilation.js | 15 +++++++------- lib/ContextModule.js | 18 ++++++++--------- lib/DelegatedModule.js | 6 +++++- lib/DllModule.js | 6 +++++- lib/ExternalModule.js | 3 ++- lib/Module.js | 4 ++-- 7 files changed, 63 insertions(+), 34 deletions(-) diff --git a/lib/ChunkGraph.js b/lib/ChunkGraph.js index 283d01b61b4..28aa3ab5c54 100644 --- a/lib/ChunkGraph.js +++ b/lib/ChunkGraph.js @@ -24,6 +24,9 @@ const findGraphRoots = require("./util/findGraphRoots"); /** @typedef {import("./ModuleGraph")} ModuleGraph */ /** @typedef {import("./RuntimeModule")} RuntimeModule */ +/** @type {ReadonlySet} */ +const EMPTY_SET = new Set(); + const compareModuleIterables = compareIterables(compareModulesByIdentifier); /** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */ @@ -167,8 +170,8 @@ class ChunkGraphModule { this.renderedHash = undefined; /** @type {string | number} */ this.id = null; - /** @type {Set} */ - this.runtimeRequirements = new Set(); + /** @type {Set | undefined} */ + this.runtimeRequirements = undefined; } } @@ -180,8 +183,8 @@ class ChunkGraphChunk { this.entryModules = new Map(); /** @type {SortableSet} */ this.runtimeModules = new SortableSet(); - /** @type {Set} */ - this.runtimeRequirements = new Set(); + /** @type {Set | undefined} */ + this.runtimeRequirements = undefined; /** @type {Set} */ this.runtimeRequirementsInTree = new Set(); } @@ -1135,24 +1138,38 @@ class ChunkGraph { /** * @param {Module} module the module - * @param {Iterable} items runtime requirements to be added + * @param {Set} items runtime requirements to be added (ownership of this Set is given to ChunkGraph) * @returns {void} */ addModuleRuntimeRequirements(module, items) { const cgm = this._getChunkGraphModule(module); const runtimeRequirements = cgm.runtimeRequirements; - for (const item of items) runtimeRequirements.add(item); + if (runtimeRequirements === undefined) { + cgm.runtimeRequirements = items; + } else if (runtimeRequirements.size >= items.size) { + for (const item of items) runtimeRequirements.add(item); + } else { + for (const item of runtimeRequirements) items.add(item); + cgm.runtimeRequirements = items; + } } /** * @param {Chunk} chunk the chunk - * @param {Iterable} items runtime requirements to be added + * @param {Set} items runtime requirements to be added (ownership of this Set is given to ChunkGraph) * @returns {void} */ addChunkRuntimeRequirements(chunk, items) { const cgc = this._getChunkGraphChunk(chunk); const runtimeRequirements = cgc.runtimeRequirements; - for (const item of items) runtimeRequirements.add(item); + if (runtimeRequirements === undefined) { + cgc.runtimeRequirements = items; + } else if (runtimeRequirements.size >= items.size) { + for (const item of items) runtimeRequirements.add(item); + } else { + for (const item of runtimeRequirements) items.add(item); + cgc.runtimeRequirements = items; + } } /** @@ -1168,25 +1185,27 @@ class ChunkGraph { /** * @param {Module} module the module - * @returns {Set} runtime requirements + * @returns {ReadonlySet} runtime requirements */ getModuleRuntimeRequirements(module) { const cgm = this._getChunkGraphModule(module); - return cgm.runtimeRequirements; + const runtimeRequirements = cgm.runtimeRequirements; + return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements; } /** * @param {Chunk} chunk the chunk - * @returns {Set} runtime requirements + * @returns {ReadonlySet} runtime requirements */ getChunkRuntimeRequirements(chunk) { const cgc = this._getChunkGraphChunk(chunk); - return cgc.runtimeRequirements; + const runtimeRequirements = cgc.runtimeRequirements; + return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements; } /** * @param {Chunk} chunk the chunk - * @returns {Set} runtime requirements + * @returns {ReadonlySet} runtime requirements */ getTreeRuntimeRequirements(chunk) { const cgc = this._getChunkGraphChunk(chunk); diff --git a/lib/Compilation.js b/lib/Compilation.js index c8db5b91260..33494bec1da 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -1292,13 +1292,13 @@ class Compilation { contextDependencies, missingDependencies } = result; - if (fileDependencies) { + if (fileDependencies && fileDependencies.size > 0) { this.fileDependencies.addAll(fileDependencies); } - if (contextDependencies) { + if (contextDependencies && contextDependencies.size > 0) { this.contextDependencies.addAll(contextDependencies); } - if (missingDependencies) { + if (missingDependencies && missingDependencies.size > 0) { this.missingDependencies.addAll(missingDependencies); } } @@ -1800,7 +1800,7 @@ class Compilation { let set; const runtimeRequirements = this.codeGenerationResults.get(module) .runtimeRequirements; - if (runtimeRequirements) { + if (runtimeRequirements && runtimeRequirements.size > 0) { set = new Set(runtimeRequirements); } else if (additionalModuleRuntimeRequirements.isUsed()) { set = new Set(); @@ -1892,9 +1892,10 @@ class Compilation { const exportsInfo = this.moduleGraph.getExportsInfo(module); exportsInfo.setHasProvideInfo(); exportsInfo.setUsedForSideEffectsOnly(); - this.chunkGraph.addModuleRuntimeRequirements(module, [ - RuntimeGlobals.requireScope - ]); + this.chunkGraph.addModuleRuntimeRequirements( + module, + new Set([RuntimeGlobals.requireScope]) + ); // runtime modules don't need ids this.chunkGraph.setModuleId(module, ""); diff --git a/lib/ContextModule.js b/lib/ContextModule.js index 6a89c635713..ec929d76dfd 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -969,25 +969,25 @@ module.exports = webpackEmptyAsyncContext;`; "javascript", this.getSource(this.getSourceString(this.options.mode, context)) ); - const set = []; + const set = new Set(); const allDeps = /** @type {ContextElementDependency[]} */ (this.dependencies.concat( this.blocks.map(b => b.dependencies[0]) )); - set.push(RuntimeGlobals.module); - set.push(RuntimeGlobals.hasOwnProperty); + set.add(RuntimeGlobals.module); + set.add(RuntimeGlobals.hasOwnProperty); if (allDeps.length > 0) { const asyncMode = this.options.mode; - set.push(RuntimeGlobals.require); + set.add(RuntimeGlobals.require); if (asyncMode === "weak") { - set.push(RuntimeGlobals.moduleFactories); + set.add(RuntimeGlobals.moduleFactories); } else if (asyncMode === "async-weak") { - set.push(RuntimeGlobals.moduleFactories); - set.push(RuntimeGlobals.ensureChunk); + set.add(RuntimeGlobals.moduleFactories); + set.add(RuntimeGlobals.ensureChunk); } else if (asyncMode === "lazy" || asyncMode === "lazy-once") { - set.push(RuntimeGlobals.ensureChunk); + set.add(RuntimeGlobals.ensureChunk); } if (this.getFakeMap(allDeps, chunkGraph) !== 9) { - set.push(RuntimeGlobals.createFakeNamespaceObject); + set.add(RuntimeGlobals.createFakeNamespaceObject); } } return { diff --git a/lib/DelegatedModule.js b/lib/DelegatedModule.js index 57c42119adb..15ca6b33a5e 100644 --- a/lib/DelegatedModule.js +++ b/lib/DelegatedModule.js @@ -31,6 +31,10 @@ const StaticExportsDependency = require("./dependencies/StaticExportsDependency" /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ const TYPES = new Set(["javascript"]); +const RUNTIME_REQUIREMENTS = new Set([ + RuntimeGlobals.module, + RuntimeGlobals.require +]); class DelegatedModule extends Module { constructor(sourceRequest, data, type, userRequest, originalRequest) { @@ -156,7 +160,7 @@ class DelegatedModule extends Module { return { sources, - runtimeRequirements: [RuntimeGlobals.module, RuntimeGlobals.require] + runtimeRequirements: RUNTIME_REQUIREMENTS }; } diff --git a/lib/DllModule.js b/lib/DllModule.js index 0bca131a5b0..3260614ea2e 100644 --- a/lib/DllModule.js +++ b/lib/DllModule.js @@ -26,6 +26,10 @@ const RuntimeGlobals = require("./RuntimeGlobals"); /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ const TYPES = new Set(["javascript"]); +const RUNTIME_REQUIREMENTS = new Set([ + RuntimeGlobals.require, + RuntimeGlobals.module +]); class DllModule extends Module { constructor(context, dependencies, name) { @@ -84,7 +88,7 @@ class DllModule extends Module { ); return { sources, - runtimeRequirements: [RuntimeGlobals.require, RuntimeGlobals.module] + runtimeRequirements: RUNTIME_REQUIREMENTS }; } diff --git a/lib/ExternalModule.js b/lib/ExternalModule.js index fddf3c01b3f..183c1fa53e7 100644 --- a/lib/ExternalModule.js +++ b/lib/ExternalModule.js @@ -124,6 +124,7 @@ const getSourceForDefaultCase = (optional, request, runtimeTemplate) => { }; const TYPES = new Set(["javascript"]); +const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]); class ExternalModule extends Module { constructor(request, type, userRequest) { @@ -261,7 +262,7 @@ class ExternalModule extends Module { sources.set("javascript", new RawSource(sourceString)); } - return { sources, runtimeRequirements: [RuntimeGlobals.module] }; + return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS }; } /** diff --git a/lib/Module.js b/lib/Module.js index cd7a15baeae..aedf532a606 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -50,7 +50,7 @@ const makeSerializable = require("./util/makeSerializable"); /** * @typedef {Object} CodeGenerationResult * @property {Map} sources the resulting sources for all source types - * @property {Iterable} runtimeRequirements the runtime requirements + * @property {ReadonlySet} runtimeRequirements the runtime requirements */ /** @@ -739,7 +739,7 @@ class Module extends DependenciesBlock { * @deprecated Use codeGeneration() instead * Get a list of runtime requirements * @param {SourceContext} context context for code generation - * @returns {Iterable | null} required runtime modules + * @returns {ReadonlySet | null} required runtime modules */ getRuntimeRequirements(context) { if (this.codeGeneration === Module.prototype.codeGeneration) {