test(compiler-cli): improve test performance using shared source file cache (#38909)

Some compiler tests take a long time to run, even using multiple
executors. A profiling session revealed that most time is spent in
parsing source files, especially the default libraries are expensive to
parse.

The default library files are constant across all tests, so this commit
introduces a shared cache of parsed source files of the default
libraries. This achieves a significant improvement for several targets
on my machine:

//packages/compiler-cli/test/compliance: from 23s to 5s.
//packages/compiler-cli/test/ngtsc: from 115s to 11s.

Note that the number of shards for the compliance tests has been halved,
as the extra shards no longer provide any speedup.

PR Close #38909
This commit is contained in:
JoostK
2020-09-13 20:31:33 +02:00
committed by Alex Rickabaugh
parent 7f6f8bbffb
commit b627f7f02e
6 changed files with 71 additions and 5 deletions

View File

@ -29,6 +29,7 @@ ts_library(
"//packages:types",
"//packages/compiler",
"//packages/compiler-cli",
"//packages/compiler-cli/test/helpers",
"@npm//typescript",
],
)

View File

@ -10,6 +10,7 @@ import {AotCompilerHost, AotCompilerOptions, createAotCompiler, GeneratedFile, t
import {MetadataBundlerHost} from '@angular/compiler-cli/src/metadata/bundler';
import {MetadataCollector} from '@angular/compiler-cli/src/metadata/collector';
import {ModuleMetadata} from '@angular/compiler-cli/src/metadata/index';
import {getCachedSourceFile} from '@angular/compiler-cli/test/helpers';
import {newArray} from '@angular/compiler/src/util';
import * as fs from 'fs';
import * as path from 'path';
@ -182,6 +183,10 @@ export class EmittingCompilerHost implements ts.CompilerHost {
onError?: (message: string) => void): ts.SourceFile {
const content = this.readFile(fileName);
if (content) {
const cachedSf = getCachedSourceFile(fileName, () => content);
if (cachedSf !== null) {
return cachedSf;
}
return ts.createSourceFile(fileName, content, languageVersion, /* setParentNodes */ true);
}
throw new Error(`File not found '${fileName}'.`);
@ -316,16 +321,20 @@ export class MockCompilerHost implements ts.CompilerHost {
// ts.CompilerHost
getSourceFile(
fileName: string, languageVersion: ts.ScriptTarget,
onError?: (message: string) => void): ts.SourceFile {
onError?: (message: string) => void): ts.SourceFile|undefined {
let result = this.sourceFiles.get(fileName);
if (!result) {
const content = this.getFileContent(fileName);
const cachedSf = getCachedSourceFile(fileName, () => content);
if (cachedSf !== null) {
return cachedSf;
}
if (content) {
result = ts.createSourceFile(fileName, content, languageVersion);
this.sourceFiles.set(fileName, result);
}
}
return result!;
return result;
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
@ -424,7 +433,7 @@ export class MockAotCompilerHost implements AotCompilerHost {
}
} else {
const sf = this.tsHost.getSourceFile(modulePath, ts.ScriptTarget.Latest);
const metadata = this.metadataProvider.getMetadata(sf);
const metadata = sf && this.metadataProvider.getMetadata(sf);
return metadata ? [metadata] : [];
}
return undefined;