ngtsc has an internal performance tracing package, which previously has not really seen much use. It used to track performance statistics on a very granular basis (microseconds per actual class analysis, for example). This had two problems: * it produced voluminous amounts of data, complicating the analysis of such results and providing dubious value. * it added nontrivial overhead to compilation when used (which also affected the very performance of the operations being measured). This commit replaces the old system with a streamlined performance tracing setup which is lightweight and designed to be always-on. The new system tracks 3 metrics: * time taken by various phases and operations within the compiler * events (counters) which measure the shape and size of the compilation * memory usage measured at various points of the compilation process If the compiler option `tracePerformance` is set, the compiler will serialize these metrics to a JSON file at that location after compilation is complete. PR Close #41125
76 lines
3.3 KiB
TypeScript
76 lines
3.3 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {CompilationTicket, freshCompilationTicket, incrementalFromCompilerTicket, NgCompiler, resourceChangeTicket} from '@angular/compiler-cli/src/ngtsc/core';
|
|
import {NgCompilerOptions} from '@angular/compiler-cli/src/ngtsc/core/api';
|
|
import {TrackedIncrementalBuildStrategy} from '@angular/compiler-cli/src/ngtsc/incremental';
|
|
import {ActivePerfRecorder} from '@angular/compiler-cli/src/ngtsc/perf';
|
|
import {TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
|
|
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
|
|
import {LanguageServiceAdapter} from './adapters';
|
|
import {isExternalTemplate} from './utils';
|
|
|
|
/**
|
|
* Manages the `NgCompiler` instance which backs the language service, updating or replacing it as
|
|
* needed to produce an up-to-date understanding of the current program.
|
|
*
|
|
* TODO(alxhub): currently the options used for the compiler are specified at `CompilerFactory`
|
|
* construction, and are not changable. In a real project, users can update `tsconfig.json`. We need
|
|
* to properly handle a change in the compiler options, either by having an API to update the
|
|
* `CompilerFactory` to use new options, or by replacing it entirely.
|
|
*/
|
|
export class CompilerFactory {
|
|
private readonly incrementalStrategy = new TrackedIncrementalBuildStrategy();
|
|
private compiler: NgCompiler|null = null;
|
|
private lastKnownProgram: ts.Program|null = null;
|
|
|
|
constructor(
|
|
private readonly adapter: LanguageServiceAdapter,
|
|
private readonly programStrategy: TypeCheckingProgramStrategy,
|
|
private readonly options: NgCompilerOptions,
|
|
) {}
|
|
|
|
getOrCreate(): NgCompiler {
|
|
const program = this.programStrategy.getProgram();
|
|
const modifiedResourceFiles = this.adapter.getModifiedResourceFiles() ?? new Set();
|
|
|
|
if (this.compiler !== null && program === this.lastKnownProgram) {
|
|
if (modifiedResourceFiles.size > 0) {
|
|
// Only resource files have changed since the last NgCompiler was created.
|
|
const ticket = resourceChangeTicket(this.compiler, modifiedResourceFiles);
|
|
this.compiler = NgCompiler.fromTicket(ticket, this.adapter);
|
|
} else {
|
|
// The previous NgCompiler is being reused, but we still want to reset its performance
|
|
// tracker to capture only the operations that are needed to service the current request.
|
|
this.compiler.perfRecorder.reset();
|
|
}
|
|
|
|
return this.compiler;
|
|
}
|
|
|
|
let ticket: CompilationTicket;
|
|
if (this.compiler === null || this.lastKnownProgram === null) {
|
|
ticket = freshCompilationTicket(
|
|
program, this.options, this.incrementalStrategy, this.programStrategy,
|
|
/* perfRecorder */ null, true, true);
|
|
} else {
|
|
ticket = incrementalFromCompilerTicket(
|
|
this.compiler, program, this.incrementalStrategy, this.programStrategy,
|
|
modifiedResourceFiles, /* perfRecorder */ null);
|
|
}
|
|
this.compiler = NgCompiler.fromTicket(ticket, this.adapter);
|
|
this.lastKnownProgram = program;
|
|
return this.compiler;
|
|
}
|
|
|
|
registerLastKnownProgram() {
|
|
this.lastKnownProgram = this.programStrategy.getProgram();
|
|
}
|
|
}
|