From 6dda170e13b7fc4edb4c05b0048cf6e5fe52da55 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 22 Oct 2015 11:54:45 -0700 Subject: [PATCH 1/3] cache results of fileExists check in default compiler host --- src/compiler/program.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d76e7585d15..85a43ac537f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -209,6 +209,7 @@ namespace ts { export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { let currentDirectory: string; let existingDirectories: Map = {}; + let existingFiles: Map = {}; function getCanonicalFileName(fileName: string): string { // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. @@ -249,6 +250,14 @@ namespace ts { return false; } + function fileExists(fileName: string): boolean { + if (hasProperty(existingFiles, fileName)) { + return existingFiles[fileName]; + } + + return existingFiles[fileName] = sys.fileExists(fileName); + } + function ensureDirectoriesExist(directoryPath: string) { if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { let parentDirectory = getDirectoryPath(directoryPath); @@ -281,7 +290,7 @@ namespace ts { useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine, - fileExists: fileName => sys.fileExists(fileName), + fileExists, readFile: fileName => sys.readFile(fileName) }; } From 7158a65b1529833321c61d7b1a8e6e760afd4bb9 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 22 Oct 2015 13:22:45 -0700 Subject: [PATCH 2/3] move 'fileExists' caching to tsc --- src/compiler/program.ts | 11 +---------- src/compiler/tsc.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 85a43ac537f..d76e7585d15 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -209,7 +209,6 @@ namespace ts { export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { let currentDirectory: string; let existingDirectories: Map = {}; - let existingFiles: Map = {}; function getCanonicalFileName(fileName: string): string { // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. @@ -250,14 +249,6 @@ namespace ts { return false; } - function fileExists(fileName: string): boolean { - if (hasProperty(existingFiles, fileName)) { - return existingFiles[fileName]; - } - - return existingFiles[fileName] = sys.fileExists(fileName); - } - function ensureDirectoriesExist(directoryPath: string) { if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { let parentDirectory = getDirectoryPath(directoryPath); @@ -290,7 +281,7 @@ namespace ts { useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine, - fileExists, + fileExists: fileName => sys.fileExists(fileName), readFile: fileName => sys.readFile(fileName) }; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index e51fda074c5..a72b5bb1b06 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -159,6 +159,9 @@ namespace ts { let timerHandleForRecompilation: number; // Handle for 0.25s wait timer to trigger recompilation let timerHandleForDirectoryChanges: number; // Handle for 0.25s wait timer to trigger directory change handler + let cachedExistingFiles: Map; + let hostFileExists: typeof compilerHost.fileExists; + if (commandLine.options.locale) { if (!isJSONSupported()) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); @@ -274,8 +277,14 @@ namespace ts { compilerHost = createCompilerHost(compilerOptions); hostGetSourceFile = compilerHost.getSourceFile; compilerHost.getSourceFile = getSourceFile; + + hostFileExists = compilerHost.fileExists; + compilerHost.fileExists = fileExists; } + // reset the cache of existing files + cachedExistingFiles = {}; + let compileResult = compile(rootFileNames, compilerOptions, compilerHost); if (!compilerOptions.watch) { @@ -286,6 +295,13 @@ namespace ts { reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); } + function fileExists(fileName: string): boolean { + if (hasProperty(cachedExistingFiles, fileName)) { + return cachedExistingFiles[fileName]; + } + return cachedExistingFiles[fileName] = hostFileExists(fileName); + } + function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) { // Return existing SourceFile object if one is available if (cachedProgram) { From 19a222e7185ad69d16573efba538823409dbd33b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 23 Oct 2015 13:09:05 -0700 Subject: [PATCH 3/3] addressed PR feedback --- src/compiler/tsc.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index a72b5bb1b06..dd0f9246d05 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -159,6 +159,8 @@ namespace ts { let timerHandleForRecompilation: number; // Handle for 0.25s wait timer to trigger recompilation let timerHandleForDirectoryChanges: number; // Handle for 0.25s wait timer to trigger directory change handler + // This map stores and reuses results of fileExists check that happen inside 'createProgram' + // This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times. let cachedExistingFiles: Map; let hostFileExists: typeof compilerHost.fileExists; @@ -279,7 +281,7 @@ namespace ts { compilerHost.getSourceFile = getSourceFile; hostFileExists = compilerHost.fileExists; - compilerHost.fileExists = fileExists; + compilerHost.fileExists = cachedFileExists; } // reset the cache of existing files @@ -295,7 +297,7 @@ namespace ts { reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); } - function fileExists(fileName: string): boolean { + function cachedFileExists(fileName: string): boolean { if (hasProperty(cachedExistingFiles, fileName)) { return cachedExistingFiles[fileName]; }