fix(bazel): Cache fileNameToModuleName lookups (#25731)

This saves expensive re-parsing of the file when not run as a Bazel worker

PR Close #25731
This commit is contained in:
Alex Eagle 2018-08-29 12:46:36 -07:00 committed by Matias Niemelä
parent 268cf7989c
commit f394ba0e27
1 changed files with 23 additions and 16 deletions

View File

@ -224,23 +224,29 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
}; };
const ngHost = ng.createCompilerHost({options: compilerOpts, tsHost: bazelHost}); const ngHost = ng.createCompilerHost({options: compilerOpts, tsHost: bazelHost});
const fileNameToModuleNameCache = new Map<string, string>();
ngHost.fileNameToModuleName = (importedFilePath: string, containingFilePath: string) => { ngHost.fileNameToModuleName = (importedFilePath: string, containingFilePath: string) => {
// Lookup the module name specified in the TypeScript source file, if present // Memoize this lookup to avoid expensive re-parses of the same file
// it will look like ///<amd module-name="something"/> // When run as a worker, the actual ts.SourceFile is cached
// For performance, we only do this for .d.ts files, to avoid parsing lots of // but when we don't run as a worker, there is no cache.
// additional files that were not in the program. // For one example target in g3, we saw a cache hit rate of 7590/7695
// (We don't have the ts.Program available in this codepath) if (fileNameToModuleNameCache.has(importedFilePath)) {
if (importedFilePath.endsWith('.d.ts')) { return fileNameToModuleNameCache.get(importedFilePath);
try { }
const sourceFile = ngHost.getSourceFile(importedFilePath, ts.ScriptTarget.Latest); const result = doFileNameToModuleName(importedFilePath);
if (sourceFile && sourceFile.moduleName) { fileNameToModuleNameCache.set(importedFilePath, result);
return sourceFile.moduleName; return result;
} };
} catch (err) {
// File does not exist or parse error. Ignore this case and continue onto the function doFileNameToModuleName(importedFilePath: string): string {
// other methods of resolving the module below. try {
const sourceFile = ngHost.getSourceFile(importedFilePath, ts.ScriptTarget.Latest);
if (sourceFile && sourceFile.moduleName) {
return sourceFile.moduleName;
} }
} catch (err) {
// File does not exist or parse error. Ignore this case and continue onto the
// other methods of resolving the module below.
} }
if ((compilerOpts.module === ts.ModuleKind.UMD || compilerOpts.module === ts.ModuleKind.AMD) && if ((compilerOpts.module === ts.ModuleKind.UMD || compilerOpts.module === ts.ModuleKind.AMD) &&
ngHost.amdModuleName) { ngHost.amdModuleName) {
@ -251,7 +257,8 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
return result.substr(NODE_MODULES.length); return result.substr(NODE_MODULES.length);
} }
return bazelOpts.workspaceName + '/' + result; return bazelOpts.workspaceName + '/' + result;
}; }
ngHost.toSummaryFileName = (fileName: string, referringSrcFileName: string) => path.posix.join( ngHost.toSummaryFileName = (fileName: string, referringSrcFileName: string) => path.posix.join(
bazelOpts.workspaceName, bazelOpts.workspaceName,
relativeToRootDirs(fileName, compilerOpts.rootDirs).replace(EXT, '')); relativeToRootDirs(fileName, compilerOpts.rootDirs).replace(EXT, ''));