Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/perf/modules-set' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed May 4, 2017
2 parents 8e85452 + df44599 commit d3ce67c
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 65 deletions.
6 changes: 3 additions & 3 deletions lib/Compilation.js
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ class Compilation extends Tapable {
if(err) return callback(err);
deps.forEach(d => {
if(d.module && d.module.removeReason(module, d)) {
module.chunks.forEach(chunk => {
module.forEachChunk(chunk => {
if(!d.module.hasReasonForChunk(chunk)) {
if(d.module.removeChunk(chunk)) {
this.removeChunkFromDependencies(d.module, chunk);
Expand Down Expand Up @@ -1018,7 +1018,7 @@ class Compilation extends Tapable {

const modules = this.modules;
for(let indexModule = 0; indexModule < modules.length; indexModule++) {
modules[indexModule].sortItems();
modules[indexModule].sortItems(false);
}

const chunks = this.chunks;
Expand All @@ -1032,7 +1032,7 @@ class Compilation extends Tapable {

const modules = this.modules;
for(let indexModule = 0; indexModule < modules.length; indexModule++) {
modules[indexModule].sortItems();
modules[indexModule].sortItems(true);
}

const chunks = this.chunks;
Expand Down
105 changes: 91 additions & 14 deletions lib/Module.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
"use strict";

const util = require("util");
const DependenciesBlock = require("./DependenciesBlock");
const ModuleReason = require("./ModuleReason");
const Template = require("./Template");
Expand All @@ -19,6 +20,10 @@ function byId(a, b) {
return a.id - b.id;
}

function byDebugId(a, b) {
return a.debugId - b.debugId;
}

let debugId = 1000;

class Module extends DependenciesBlock {
Expand All @@ -36,7 +41,10 @@ class Module extends DependenciesBlock {
this.used = null;
this.usedExports = null;
this.providedExports = null;
this.chunks = [];
this._chunks = new Set();
this._chunksIsSorted = true;
this._chunksIsSortedByDebugId = true;
this._chunksDebugIdent = undefined;
this.warnings = [];
this.dependenciesWarnings = [];
this.errors = [];
Expand All @@ -55,7 +63,9 @@ class Module extends DependenciesBlock {
this.used = null;
this.usedExports = null;
this.providedExports = null;
this.chunks.length = 0;
this._chunks.clear();
this._chunksDebugIdent = undefined;
this._chunksIsSorted = this._chunksIsSortedByDebugId = false;
super.disconnect();
}

Expand All @@ -65,26 +75,81 @@ class Module extends DependenciesBlock {
this.index = null;
this.index2 = null;
this.depth = null;
this.chunks.length = 0;
this._chunks.clear();
this._chunksDebugIdent = undefined;
this._chunksIsSorted = this._chunksIsSortedByDebugId = false;
super.unseal();
}

addChunk(chunk) {
let idx = this.chunks.indexOf(chunk);
if(idx < 0)
this.chunks.push(chunk);
this._chunks.add(chunk);
this._chunksDebugIdent = undefined;
this._chunksIsSorted = this._chunksIsSortedByDebugId = false;
}

removeChunk(chunk) {
let idx = this.chunks.indexOf(chunk);
if(idx >= 0) {
this.chunks.splice(idx, 1);
if(this._chunks.delete(chunk)) {
this._chunksDebugIdent = undefined;
chunk.removeModule(this);
return true;
}
return false;
}

isInChunk(chunk) {
return this._chunks.has(chunk);
}

getChunkIdsIdent() {
if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent;
this._ensureChunksSortedByDebugId();
const chunks = this._chunks;
const list = [];
for(let chunk of chunks) {
const debugId = chunk.debugId;

if(typeof debugId !== "number") {
return this._chunksDebugIdent = null;
}

list.push(debugId);
}

return this._chunksDebugIdent = list.join(",");
}

forEachChunk(fn) {
this._chunks.forEach(fn);
}

mapChunks(fn) {
const chunks = this._chunks;
const array = new Array(chunks.size);
let idx = 0;
for(let chunk of chunks) {
array[idx++] = fn(chunk, idx, chunks);
}
return array;
}

getNumberOfChunks() {
return this._chunks.size;
}

_ensureChunksSorted() {
if(this._chunksIsSorted) return;
this._chunks = new Set(Array.from(this._chunks).sort(byId));
this._chunksIsSortedByDebugId = false;
this._chunksIsSorted = true;
}

_ensureChunksSortedByDebugId() {
if(this._chunksIsSortedByDebugId) return;
this._chunks = new Set(Array.from(this._chunks).sort(byDebugId));
this._chunksIsSorted = false;
this._chunksIsSortedByDebugId = true;
}

addReason(module, dependency) {
this.reasons.push(new ModuleReason(module, dependency));
}
Expand All @@ -105,7 +170,7 @@ class Module extends DependenciesBlock {
if(r.chunks) {
if(r.chunks.indexOf(chunk) >= 0)
return true;
} else if(r.module.chunks.indexOf(chunk) >= 0)
} else if(r.module._chunks.has(chunk))
return true;
}
return false;
Expand All @@ -114,9 +179,9 @@ class Module extends DependenciesBlock {
rewriteChunkInReasons(oldChunk, newChunks) {
this.reasons.forEach(r => {
if(!r.chunks) {
if(r.module.chunks.indexOf(oldChunk) < 0)
if(!r.module._chunks.has(oldChunk))
return;
r.chunks = r.module.chunks;
r.chunks = Array.from(r.module._chunks);
}
r.chunks = r.chunks.reduce((arr, c) => {
addToSet(arr, c !== oldChunk ? [c] : newChunks);
Expand Down Expand Up @@ -158,9 +223,10 @@ class Module extends DependenciesBlock {
super.updateHash(hash);
}

sortItems() {
sortItems(sortChunks) {
super.sortItems();
this.chunks.sort(byId);
if(sortChunks)
this._ensureChunksSorted();
this.reasons.sort((a, b) => byId(a.module, b.module));
}

Expand All @@ -178,6 +244,17 @@ Object.defineProperty(Module.prototype, "entry", {
throw new Error("Module.entry was removed. Use Chunk.entryModule");
}
});

Object.defineProperty(Module.prototype, "chunks", {
configurable: false,
get: util.deprecate(() => {
return Array.from(this._chunks);
}, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
set() {
throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");
}
});

Module.prototype.identifier = null;
Module.prototype.readableIdentifier = null;
Module.prototype.build = null;
Expand Down
2 changes: 1 addition & 1 deletion lib/ModuleFilenameHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ ModuleFilenameHelpers.createFooter = function createFooter(module, requestShorte
"// WEBPACK FOOTER",
`// ${module.readableIdentifier(requestShortener)}`,
`// module id = ${module.id}`,
`// module chunks = ${module.chunks.map(c => c.id).join(" ")}`
`// module chunks = ${module.mapChunks(c => c.id).join(" ")}`
].join("\n");
}
};
Expand Down
2 changes: 1 addition & 1 deletion lib/Stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ class Stats {
built: !!module.built,
optional: !!module.optional,
prefetched: !!module.prefetched,
chunks: module.chunks.map(chunk => chunk.id),
chunks: module.mapChunks(chunk => chunk.id),
assets: Object.keys(module.assets || {}),
issuer: module.issuer && module.issuer.identifier(),
issuerId: module.issuer && module.issuer.id,
Expand Down
21 changes: 12 additions & 9 deletions lib/optimize/OccurrenceOrderPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class OccurrenceOrderPlugin {
compiler.plugin("compilation", (compilation) => {
compilation.plugin("optimize-module-order", (modules) => {
function entryChunks(m) {
return m.chunks.map((c) => {
let total = 0;
m.forEachChunk(c => {
const sum = (c.isInitial() ? 1 : 0) + (c.entryModule === m ? 1 : 0);
return sum;
}).reduce((a, b) => {
return a + b;
}, 0);
total += sum;
});
return total;
}

function occursInEntry(m) {
Expand All @@ -37,14 +37,17 @@ class OccurrenceOrderPlugin {

function occurs(m) {
if(typeof m.__OccurenceOrderPlugin_occurs === "number") return m.__OccurenceOrderPlugin_occurs;
let numberEntry = 0;
m.forEachChunk(c => {
if(c.entryModule === m)
numberEntry++;
});
const result = m.reasons.map((r) => {
if(!r.module) return 0;
return r.module.chunks.length;
return r.module.getNumberOfChunks();
}).reduce((a, b) => {
return a + b;
}, 0) + m.chunks.length + m.chunks.filter((c) => {
return c.entryModule === m;
}).length;
}, 0) + m.getNumberOfChunks() + numberEntry;
return m.__OccurenceOrderPlugin_occurs = result;
}
modules.sort((a, b) => {
Expand Down
48 changes: 11 additions & 37 deletions lib/optimize/RemoveParentModulesPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,31 @@
*/
"use strict";

function chunkContainsModule(chunk, module) {
const chunks = module.chunks;
const modules = chunk.modules;
if(chunks.length < modules.length) {
return chunks.indexOf(chunk) >= 0;
} else {
return modules.indexOf(module) >= 0;
}
}

function hasModule(chunk, module, checkedChunks) {
if(chunkContainsModule(chunk, module)) return [chunk];
if(module.isInChunk(chunk)) return [chunk];
if(chunk.parents.length === 0) return false;
return allHaveModule(chunk.parents.filter((c) => {
return checkedChunks.indexOf(c) < 0;
return !checkedChunks.has(c);
}), module, checkedChunks);
}

function allHaveModule(someChunks, module, checkedChunks) {
if(!checkedChunks) checkedChunks = [];
var chunks = [];
if(!checkedChunks) checkedChunks = new Set();
var chunks = new Set();
for(var i = 0; i < someChunks.length; i++) {
checkedChunks.push(someChunks[i]);
checkedChunks.add(someChunks[i]);
var subChunks = hasModule(someChunks[i], module, checkedChunks);
if(!subChunks) return false;

for(var index = 0; index < subChunks.length; index++) {
var item = subChunks[index];

if(!chunks.length || chunks.indexOf(item) < 0) {
chunks.push(item);
}
chunks.add(item);
}
}
return chunks;
}

function debugIds(chunks) {
var list = [];
for(var i = 0; i < chunks.length; i++) {
var debugId = chunks[i].debugId;

if(typeof debugId !== "number") {
return "no";
}

list.push(debugId);
}

list.sort();
return list.join(",");
}

class RemoveParentModulesPlugin {
apply(compiler) {
compiler.plugin("compilation", (compilation) => {
Expand All @@ -71,15 +43,17 @@ class RemoveParentModulesPlugin {
for(var i = 0; i < modules.length; i++) {
var module = modules[i];

var dId = debugIds(module.chunks);
var dId = module.getChunkIdsIdent();
var parentChunksWithModule;
if((dId in cache) && dId !== "no") {
if(dId === null) {
parentChunksWithModule = allHaveModule(chunk.parents, module);
} else if(dId in cache) {
parentChunksWithModule = cache[dId];
} else {
parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);
}
if(parentChunksWithModule) {
module.rewriteChunkInReasons(chunk, parentChunksWithModule);
module.rewriteChunkInReasons(chunk, Array.from(parentChunksWithModule));
chunk.removeModule(module);
}
}
Expand Down

0 comments on commit d3ce67c

Please sign in to comment.