From 84e475c105e1e66d5fb01d3135f28c25b0e5b067 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 6 Dec 2022 14:25:19 -0800 Subject: [PATCH] Make resolution cache use sets instead of arrays for easier checking (#51735) --- src/compiler/resolutionCache.ts | 45 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 030e837a26e..1f8d9e179fe 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -41,7 +41,6 @@ import { isNodeModulesDirectory, isRootedDiskPath, isTraceEnabled, - length, loadModuleFromGlobalCache, memoize, MinimalResolutionCacheHost, @@ -72,7 +71,6 @@ import { stringContains, StringLiteralLike, trace, - unorderedRemoveItem, updateResolutionField, WatchDirectoryFlags, } from "./_namespaces/ts"; @@ -136,7 +134,7 @@ export interface ResolutionWithFailedLookupLocations { isInvalidated?: boolean; refCount?: number; // Files that have this resolution using - files?: Path[]; + files?: Set; } interface ResolutionWithResolvedFileName { @@ -268,9 +266,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap | undefined; const nonRelativeExternalModuleResolutions = createMultiMap(); - const resolutionsWithFailedLookups: ResolutionWithFailedLookupLocations[] = []; - const resolutionsWithOnlyAffectingLocations: ResolutionWithFailedLookupLocations[] = []; - const resolvedFileToResolution = createMultiMap(); + const resolutionsWithFailedLookups = new Set(); + const resolutionsWithOnlyAffectingLocations = new Set(); + const resolvedFileToResolution = new Map>(); const impliedFormatPackageJsons = new Map(); let hasChangedAutomaticTypeDirectiveNames = false; @@ -367,8 +365,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolvedModuleNames.clear(); resolvedTypeReferenceDirectives.clear(); resolvedFileToResolution.clear(); - resolutionsWithFailedLookups.length = 0; - resolutionsWithOnlyAffectingLocations.length = 0; + resolutionsWithFailedLookups.clear(); + resolutionsWithOnlyAffectingLocations.clear(); failedLookupChecks = undefined; startsWithPathChecks = undefined; isInDirectoryChecks = undefined; @@ -782,7 +780,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } else { resolution.refCount = 1; - Debug.assert(length(resolution.files) === 0); // This resolution shouldnt be referenced by any file yet + Debug.assert(!resolution.files?.size); // This resolution shouldnt be referenced by any file yet if (isExternalModuleNameRelative(name)) { watchFailedLookupLocationOfResolution(resolution); } @@ -791,10 +789,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } const resolved = getResolutionWithResolvedFileName(resolution); if (resolved && resolved.resolvedFileName) { - resolvedFileToResolution.add(resolutionHost.toPath(resolved.resolvedFileName), resolution); + const key = resolutionHost.toPath(resolved.resolvedFileName); + let resolutions = resolvedFileToResolution.get(key); + if (!resolutions) resolvedFileToResolution.set(key, resolutions = new Set()); + resolutions.add(resolution); } } - (resolution.files || (resolution.files = [])).push(filePath); + (resolution.files ??= new Set()).add(filePath); } function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) { @@ -802,7 +803,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const { failedLookupLocations, affectingLocations } = resolution; if (!failedLookupLocations?.length && !affectingLocations?.length) return; - if (failedLookupLocations?.length) resolutionsWithFailedLookups.push(resolution); + if (failedLookupLocations?.length) resolutionsWithFailedLookups.add(resolution); let setAtRoot = false; if (failedLookupLocations) { @@ -839,7 +840,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD Debug.assert(!!resolution.refCount); const { affectingLocations } = resolution; if (!affectingLocations?.length) return; - if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.push(resolution); + if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution); // Watch package json for (const affectingLocation of affectingLocations) { createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true); @@ -925,18 +926,20 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, ) { - unorderedRemoveItem(Debug.checkDefined(resolution.files), filePath); + Debug.checkDefined(resolution.files).delete(filePath); resolution.refCount!--; if (resolution.refCount) { return; } const resolved = getResolutionWithResolvedFileName(resolution); if (resolved && resolved.resolvedFileName) { - resolvedFileToResolution.remove(resolutionHost.toPath(resolved.resolvedFileName), resolution); + const key = resolutionHost.toPath(resolved.resolvedFileName); + const resolutions = resolvedFileToResolution.get(key); + if (resolutions?.delete(resolution) && !resolutions.size) resolvedFileToResolution.delete(key); } const { failedLookupLocations, affectingLocations } = resolution; - if (unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) { + if (resolutionsWithFailedLookups.delete(resolution)) { let removeAtRoot = false; for (const failedLookupLocation of failedLookupLocations!) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); @@ -967,7 +970,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } else if (affectingLocations?.length) { - unorderedRemoveItem(resolutionsWithOnlyAffectingLocations, resolution); + resolutionsWithOnlyAffectingLocations.delete(resolution); } if (affectingLocations) { @@ -1028,18 +1031,18 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective); } - function invalidateResolutions(resolutions: ResolutionWithFailedLookupLocations[] | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) { + function invalidateResolutions(resolutions: Set | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) { if (!resolutions) return false; let invalidated = false; - for (const resolution of resolutions) { - if (resolution.isInvalidated || !canInvalidate(resolution)) continue; + resolutions.forEach(resolution => { + if (resolution.isInvalidated || !canInvalidate(resolution)) return; resolution.isInvalidated = invalidated = true; for (const containingFilePath of Debug.checkDefined(resolution.files)) { (filesWithInvalidatedResolutions ??= new Set()).add(containingFilePath); // When its a file with inferred types resolution, invalidate type reference directive resolution hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith(containingFilePath, inferredTypesContainingFile); } - } + }); return invalidated; }