Skip to content

Commit 0f6e6ef

Browse files
authored
Avoid no-op export map updates (microsoft#45238)
* Add id and version to ManyToManyPathMap ...so that unchanged maps can be recognized without having to examine their contents. * Track cache version on BuilderState In practice, `updateExportedFilesMapFromCache` is called repeatedly without the cache changing in between. When this occurs, there's no need to update the `BuilderState` (this was already the net effect, but it took a long time to determine that no work was required). * Fix typo in comment
1 parent 9d957c6 commit 0f6e6ef

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

src/compiler/builderState.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ namespace ts {
4848
*/
4949
readonly exportedModulesMap: BuilderState.ManyToManyPathMap | undefined;
5050

51+
previousCache?: {
52+
id: number,
53+
version: number,
54+
};
55+
5156
/**
5257
* true if file version is used as signature
5358
* This helps in delaying the calculation of the d.ts hash as version for the file till reasonable time
@@ -80,6 +85,7 @@ namespace ts {
8085
}
8186

8287
export interface ReadonlyManyToManyPathMap {
88+
readonly id: number;
8389
clone(): ManyToManyPathMap;
8490
forEach(action: (v: ReadonlySet<Path>, k: Path) => void): void;
8591
getKeys(v: Path): ReadonlySet<Path> | undefined;
@@ -96,13 +102,18 @@ namespace ts {
96102
}
97103

98104
export interface ManyToManyPathMap extends ReadonlyManyToManyPathMap {
105+
version(): number; // Incremented each time the contents are changed
99106
deleteKey(k: Path): boolean;
100107
set(k: Path, v: ReadonlySet<Path>): void;
101108
}
102109

110+
let manyToManyPathMapCount = 0;
103111
export function createManyToManyPathMap(): ManyToManyPathMap {
104112
function create(forward: ESMap<Path, ReadonlySet<Path>>, reverse: ESMap<Path, Set<Path>>, deleted: Set<Path> | undefined): ManyToManyPathMap {
113+
let version = 0;
105114
const map: ManyToManyPathMap = {
115+
id: manyToManyPathMapCount++,
116+
version: () => version,
106117
clone: () => create(new Map(forward), new Map(reverse), deleted && new Set(deleted)),
107118
forEach: fn => forward.forEach(fn),
108119
getKeys: v => reverse.get(v),
@@ -121,26 +132,33 @@ namespace ts {
121132

122133
set.forEach(v => deleteFromMultimap(reverse, v, k));
123134
forward.delete(k);
135+
version++;
124136
return true;
125137
},
126138
set: (k, vSet) => {
127-
deleted?.delete(k);
139+
let changed = !!deleted?.delete(k);
128140

129141
const existingVSet = forward.get(k);
130142
forward.set(k, vSet);
131143

132144
existingVSet?.forEach(v => {
133145
if (!vSet.has(v)) {
146+
changed = true;
134147
deleteFromMultimap(reverse, v, k);
135148
}
136149
});
137150

138151
vSet.forEach(v => {
139152
if (!existingVSet?.has(v)) {
153+
changed = true;
140154
addToMultimap(reverse, v, k);
141155
}
142156
});
143157

158+
if (changed) {
159+
version++;
160+
}
161+
144162
return map;
145163
},
146164
};
@@ -475,6 +493,22 @@ namespace ts {
475493
export function updateExportedFilesMapFromCache(state: BuilderState, exportedModulesMapCache: ManyToManyPathMap | undefined) {
476494
if (exportedModulesMapCache) {
477495
Debug.assert(!!state.exportedModulesMap);
496+
497+
const cacheId = exportedModulesMapCache.id;
498+
const cacheVersion = exportedModulesMapCache.version();
499+
if (state.previousCache) {
500+
if (state.previousCache.id === cacheId && state.previousCache.version === cacheVersion) {
501+
// If this is the same cache at the same version as last time this BuilderState
502+
// was updated, there's no need to update again
503+
return;
504+
}
505+
state.previousCache.id = cacheId;
506+
state.previousCache.version = cacheVersion;
507+
}
508+
else {
509+
state.previousCache = { id: cacheId, version: cacheVersion };
510+
}
511+
478512
exportedModulesMapCache.deletedKeys()?.forEach(path => state.exportedModulesMap!.deleteKey(path));
479513
exportedModulesMapCache.forEach((exportedModules, path) => state.exportedModulesMap!.set(path, exportedModules));
480514
}

0 commit comments

Comments
 (0)