Skip to content

Commit 49cdb94

Browse files
authored
Merge pull request webpack#5917 from webpack/refactor/cache-sortable-set
allow caching in sortable set and use it
2 parents 5fae802 + c585ea6 commit 49cdb94

File tree

3 files changed

+91
-51
lines changed

3 files changed

+91
-51
lines changed

lib/Chunk.js

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@ const sortByIdentifier = (a, b) => {
2121
return 0;
2222
};
2323

24+
const getFrozenArray = set => Object.freeze(Array.from(set));
25+
26+
const getModulesIdent = set => {
27+
set.sort();
28+
let str = "";
29+
set.forEach(m => {
30+
str += m.identifier() + "#";
31+
});
32+
return str;
33+
};
34+
35+
const getArray = set => Array.from(set);
36+
37+
const getModulesSize = set => {
38+
let count = 0;
39+
for(const module of set) {
40+
count += module.size();
41+
}
42+
return count;
43+
};
44+
2445
class Chunk {
2546

2647
constructor(name, module, loc) {
@@ -65,7 +86,7 @@ class Chunk {
6586
* @return {Array} - an array containing the chunks
6687
*/
6788
getChunks() {
68-
return Array.from(this._chunks);
89+
return this._chunks.getFromCache(getArray);
6990
}
7091

7192
getNumberOfChunks() {
@@ -80,7 +101,7 @@ class Chunk {
80101
* @return {Array} - an array containing the parents
81102
*/
82103
getParents() {
83-
return Array.from(this._parents);
104+
return this._parents.getFromCache(getArray);
84105
}
85106

86107
setParents(newParents) {
@@ -109,7 +130,7 @@ class Chunk {
109130
* @return {Array} - an array containing the blocks
110131
*/
111132
getBlocks() {
112-
return Array.from(this._blocks);
133+
return this._blocks.getFromCache(getArray);
113134
}
114135

115136
setBlocks(newBlocks) {
@@ -269,16 +290,11 @@ class Chunk {
269290
}
270291

271292
getModules() {
272-
return Array.from(this._modules);
293+
return this._modules.getFromCache(getArray);
273294
}
274295

275296
getModulesIdent() {
276-
this._modules.sort();
277-
let str = "";
278-
this._modules.forEach(m => {
279-
str += m.identifier() + "#";
280-
});
281-
return str;
297+
return this._modules.getFromUnorderedCache(getModulesIdent);
282298
}
283299

284300
remove(reason) {
@@ -452,11 +468,7 @@ class Chunk {
452468
}
453469

454470
modulesSize() {
455-
let count = 0;
456-
for(const module of this._modules) {
457-
count += module.size();
458-
}
459-
return count;
471+
return this._modules.getFromUnorderedCache(getModulesSize);
460472
}
461473

462474
size(options) {
@@ -543,7 +555,7 @@ class Chunk {
543555
Object.defineProperty(Chunk.prototype, "modules", {
544556
configurable: false,
545557
get: util.deprecate(function() {
546-
return this._modules.getFrozenArray();
558+
return this._modules.getFromCache(getFrozenArray);
547559
}, "Chunk.modules is deprecated. Use Chunk.getNumberOfModules/mapModules/forEachModule/containsModule instead."),
548560
set: util.deprecate(function(value) {
549561
this.setModules(value);
@@ -553,7 +565,7 @@ Object.defineProperty(Chunk.prototype, "modules", {
553565
Object.defineProperty(Chunk.prototype, "chunks", {
554566
configurable: false,
555567
get: util.deprecate(function() {
556-
return this._chunks.getFrozenArray();
568+
return this._chunks.getFromCache(getFrozenArray);
557569
}, "Chunk.chunks: Use Chunk.getChunks() instead"),
558570
set() {
559571
throw new Error("Readonly. Use Chunk.addChunk/removeChunk/getChunks to access/modify chunks.");
@@ -563,7 +575,7 @@ Object.defineProperty(Chunk.prototype, "chunks", {
563575
Object.defineProperty(Chunk.prototype, "parents", {
564576
configurable: false,
565577
get: util.deprecate(function() {
566-
return this._parents.getFrozenArray();
578+
return this._parents.getFromCache(getFrozenArray);
567579
}, "Chunk.parents: Use Chunk.getParents() instead"),
568580
set: util.deprecate(function(value) {
569581
this.setParents(value);
@@ -573,7 +585,7 @@ Object.defineProperty(Chunk.prototype, "parents", {
573585
Object.defineProperty(Chunk.prototype, "blocks", {
574586
configurable: false,
575587
get: util.deprecate(function() {
576-
return this._blocks.getFrozenArray();
588+
return this._blocks.getFromCache(getFrozenArray);
577589
}, "Chunk.blocks: Use Chunk.getBlocks() instead"),
578590
set: util.deprecate(function(value) {
579591
this.setBlocks(value);

lib/Module.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,25 @@ const sortByDebugId = (a, b) => {
2121
return a.debugId - b.debugId;
2222
};
2323

24+
const getFrozenArray = set => Object.freeze(Array.from(set));
25+
26+
const getDebugIdent = set => {
27+
set.sortWith(sortByDebugId);
28+
const chunks = set;
29+
const list = [];
30+
for(const chunk of chunks) {
31+
const debugId = chunk.debugId;
32+
33+
if(typeof debugId !== "number") {
34+
return null;
35+
}
36+
37+
list.push(debugId);
38+
}
39+
40+
return list.join(",");
41+
};
42+
2443
class Module extends DependenciesBlock {
2544

2645
constructor() {
@@ -37,7 +56,6 @@ class Module extends DependenciesBlock {
3756
this.usedExports = null;
3857
this.providedExports = null;
3958
this._chunks = new SortableSet(undefined, sortById);
40-
this._chunksDebugIdent = undefined;
4159
this.warnings = [];
4260
this.dependenciesWarnings = [];
4361
this.errors = [];
@@ -57,7 +75,6 @@ class Module extends DependenciesBlock {
5775
this.usedExports = null;
5876
this.providedExports = null;
5977
this._chunks.clear();
60-
this._chunksDebugIdent = undefined;
6178
this.optimizationBailout.length = 0;
6279
super.disconnect();
6380
}
@@ -68,23 +85,19 @@ class Module extends DependenciesBlock {
6885
this.index2 = null;
6986
this.depth = null;
7087
this._chunks.clear();
71-
this._chunksDebugIdent = undefined;
7288
super.unseal();
7389
}
7490

7591
setChunks(chunks) {
7692
this._chunks = new SortableSet(chunks, sortById);
77-
this._chunksDebugIdent = undefined;
7893
}
7994

8095
addChunk(chunk) {
8196
this._chunks.add(chunk);
82-
this._chunksDebugIdent = undefined;
8397
}
8498

8599
removeChunk(chunk) {
86100
if(this._chunks.delete(chunk)) {
87-
this._chunksDebugIdent = undefined;
88101
chunk.removeModule(this);
89102
return true;
90103
}
@@ -96,21 +109,7 @@ class Module extends DependenciesBlock {
96109
}
97110

98111
getChunkIdsIdent() {
99-
if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent;
100-
this._chunks.sortWith(sortByDebugId);
101-
const chunks = this._chunks;
102-
const list = [];
103-
for(const chunk of chunks) {
104-
const debugId = chunk.debugId;
105-
106-
if(typeof debugId !== "number") {
107-
return this._chunksDebugIdent = null;
108-
}
109-
110-
list.push(debugId);
111-
}
112-
113-
return this._chunksDebugIdent = list.join(",");
112+
return this._chunks.getFromUnorderedCache(getDebugIdent);
114113
}
115114

116115
forEachChunk(fn) {
@@ -237,7 +236,7 @@ Object.defineProperty(Module.prototype, "entry", {
237236
Object.defineProperty(Module.prototype, "chunks", {
238237
configurable: false,
239238
get: util.deprecate(function() {
240-
return this._chunks.getFrozenArray();
239+
return this._chunks.getFromCache(getFrozenArray);
241240
}, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
242241
set() {
243242
throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");

lib/util/SortableSet.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ module.exports = class SortableSet extends Set {
66
super(initialIterable);
77
this._sortFn = defaultSort;
88
this._lastActiveSortFn = null;
9-
this._frozenArray = null;
9+
this._cache = null;
10+
this._cacheOrderIndependent = null;
1011
}
1112

1213
/**
@@ -15,18 +16,21 @@ module.exports = class SortableSet extends Set {
1516
*/
1617
add(value) {
1718
this._lastActiveSortFn = null;
18-
this._frozenArray = null;
19+
this._cache = null;
20+
this._cacheOrderIndependent = null;
1921
super.add(value);
2022
return this;
2123
}
2224

2325
delete(value) {
24-
this._frozenArray = null;
26+
this._cache = null;
27+
this._cacheOrderIndependent = null;
2528
return super.delete(value);
2629
}
2730

2831
clear() {
29-
this._frozenArray = null;
32+
this._cache = null;
33+
this._cacheOrderIndependent = null;
3034
return super.clear();
3135
}
3236

@@ -46,7 +50,7 @@ module.exports = class SortableSet extends Set {
4650
super.add(sortedArray[i]);
4751
}
4852
this._lastActiveSortFn = sortFn;
49-
this._frozenArray = null;
53+
this._cache = null;
5054
}
5155

5256
/**
@@ -57,12 +61,37 @@ module.exports = class SortableSet extends Set {
5761
}
5862

5963
/**
60-
* @returns {any[]} - returns content as frozen array
64+
* @param {Function} fn - function to calculate value
65+
* @returns {any} - returns result of fn(this), cached until set changes
6166
*/
62-
getFrozenArray() {
63-
if(this._frozenArray === null) {
64-
this._frozenArray = Object.freeze(Array.from(this));
67+
getFromCache(fn) {
68+
if(this._cache === null) {
69+
this._cache = new Map();
70+
} else {
71+
const data = this._cache.get(fn);
72+
if(data !== undefined) {
73+
return data;
74+
}
6575
}
66-
return this._frozenArray;
76+
const newData = fn(this);
77+
this._cache.set(fn, newData);
78+
return newData;
79+
}
80+
/**
81+
* @param {Function} fn - function to calculate value
82+
* @returns {any} - returns result of fn(this), cached until set changes
83+
*/
84+
getFromUnorderedCache(fn) {
85+
if(this._cacheOrderIndependent === null) {
86+
this._cacheOrderIndependent = new Map();
87+
} else {
88+
const data = this._cacheOrderIndependent.get(fn);
89+
if(data !== undefined) {
90+
return data;
91+
}
92+
}
93+
const newData = fn(this);
94+
this._cacheOrderIndependent.set(fn, newData);
95+
return newData;
6796
}
6897
};

0 commit comments

Comments
 (0)