Experiment using caches to answer readFile, fileExists

This commit is contained in:
Sheetal Nandi 2023-12-05 12:49:43 -08:00
Родитель 993ffd70e6
Коммит 71a3cfdea2
2 изменённых файлов: 31 добавлений и 8 удалений

Просмотреть файл

@ -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[];

Просмотреть файл

@ -759,6 +759,13 @@ function enableCache<T extends BuilderProgram>(state: SolutionBuilderState<T>) {
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<T extends BuilderProgram>(state: SolutionBuilderState<T>)
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<T extends BuilderProgram>(state: SolutionBuilderState<T>, 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<T extends BuilderProgram>(state: SolutionBuilderState<T
// This is either Date | FileWatcherWithModifiedTime because we query modified times first and
// then after complete compilation of the project, watch the files so we dont want to loose these modified times.
const result = ts_getModifiedTime(state.host, fileName);
if (state.watch) {
if (existing) (existing as FileWatcherWithModifiedTime).modifiedTime = result;
else state.filesWatched.set(path, result);
}
if (existing) existing.modifiedTime = result;
else state.filesWatched.set(path, result);
return result;
}