From 71a3cfdea2b8e37b6dffeeb12378f225587488fc Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 5 Dec 2023 12:49:43 -0800 Subject: [PATCH] Experiment using caches to answer readFile, fileExists --- src/compiler/program.ts | 23 ++++++++++++++++++++--- src/compiler/tsbuildPublic.ts | 16 +++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b92bfa27b65..3a2c0836491 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -217,6 +217,7 @@ import { maybeBind, memoize, MethodDeclaration, + missingFileModifiedTime, ModeAwareCache, ModeAwareCacheKey, ModifierFlags, @@ -515,6 +516,7 @@ export function changeCompilerHostLikeToUseCache( host: CompilerHostLikeForCache, toPath: (fileName: string) => Path, getSourceFile?: CompilerHost["getSourceFile"], + getModifiedTime?: (path: Path) => Date | undefined, ) { const originalReadFile = host.readFile; const originalFileExists = host.fileExists; @@ -533,7 +535,7 @@ export function changeCompilerHostLikeToUseCache( return setReadFileCache(key, fileName); }; const setReadFileCache = (key: Path, fileName: string) => { - const newValue = originalReadFile.call(host, fileName); + const newValue = readFile(key, fileName); readFileCache.set(key, newValue !== undefined ? newValue : false); return newValue; }; @@ -543,7 +545,7 @@ export function changeCompilerHostLikeToUseCache( if (value !== undefined) return value !== false ? value : undefined; // could be .d.ts from output // Cache json or buildInfo if (!fileExtensionIs(fileName, Extension.Json) && !isBuildInfoFile(fileName)) { - return originalReadFile.call(host, fileName); + return readFile(key, fileName); } return setReadFileCache(key, fileName); @@ -568,7 +570,7 @@ export function changeCompilerHostLikeToUseCache( const key = toPath(fileName); const value = fileExistsCache.get(key); if (value !== undefined) return value; - const newValue = originalFileExists.call(host, fileName); + const newValue = fileExists(key, fileName); fileExistsCache.set(key, !!newValue); return newValue; }; @@ -623,6 +625,21 @@ export function changeCompilerHostLikeToUseCache( getSourceFileWithCache, readFileWithCache, }; + + function readFile(key: Path, fileName: string) { + return fileExistsCache.get(key) !== false || getModifiedTime?.(key) !== missingFileModifiedTime ? + originalReadFile.call(host, fileName) : + undefined; + } + + function fileExists(key: Path, fileName: string) { + const text = readFileCache.get(key); + if (text !== undefined) return text !== false; + const modifiedTime = getModifiedTime?.(key); + return modifiedTime === undefined ? + originalFileExists.call(host, fileName) : + modifiedTime !== missingFileModifiedTime; + } } export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 902e57184fa..34d2d1c0fac 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -759,6 +759,13 @@ function enableCache(state: SolutionBuilderState) { host, fileName => toPath(state, fileName), (...args) => originalGetSourceFile.call(compilerHost, ...args), + path => { + const existing = state.filesWatched.get(path); + if (!!existing) { + if (!isFileWatcherWithModifiedTime(existing)) return existing; + if (existing.modifiedTime) return existing.modifiedTime; + } + }, ); state.readFileWithCache = readFileWithCache; compilerHost.getSourceFile = getSourceFileWithCache!; @@ -786,6 +793,7 @@ function disableCache(state: SolutionBuilderState) host.writeFile = cache.originalWriteFile; compilerHost.getSourceFile = cache.originalGetSourceFile; state.readFileWithCache = cache.originalReadFileWithCache; + if (!state.watch) state.filesWatched.clear(); extendedConfigCache.clear(); moduleResolutionCache?.clear(); typeReferenceDirectiveResolutionCache?.clear(); @@ -1597,7 +1605,7 @@ function isFileWatcherWithModifiedTime(value: FileWatcherWithModifiedTime | Date function getModifiedTime(state: SolutionBuilderState, fileName: string): Date { const path = toPath(state, fileName); const existing = state.filesWatched.get(path); - if (state.watch && !!existing) { + if (!!existing) { if (!isFileWatcherWithModifiedTime(existing)) return existing; if (existing.modifiedTime) return existing.modifiedTime; } @@ -1605,10 +1613,8 @@ function getModifiedTime(state: SolutionBuilderState