Skip to content

Commit

Permalink
Report aggregate statistics for solution as well as some solution per…
Browse files Browse the repository at this point in the history
…f numbers (microsoft#50267)

* Report aggregate statistics for solution as well as some solution perf numbers
This change under --extendedDiagnostics aggregates the diagnostics from all projects built and reports it at the end. Apart from that it also outputs some measurements for work that happens in tsc --build like finding if projects are uptodate etc.
Also removes unnecessary node count per suggestion

* Apply suggestions from code review

Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>

* Fix condition

* Remove extra time

Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>
  • Loading branch information
sheetalkamat and rbuckton authored Aug 11, 2022
1 parent 075ee3d commit b19741c
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 63 deletions.
22 changes: 22 additions & 0 deletions src/compiler/performance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,28 @@ namespace ts.performance {
durations.forEach((duration, measureName) => cb(measureName, duration));
}

export function forEachMark(cb: (markName: string) => void) {
marks.forEach((_time, markName) => cb(markName));
}

export function clearMeasures(name?: string) {
if (name !== undefined) durations.delete(name);
else durations.clear();
performanceImpl?.clearMeasures(name);
}

export function clearMarks(name?: string) {
if (name !== undefined) {
counts.delete(name);
marks.delete(name);
}
else {
counts.clear();
marks.clear();
}
performanceImpl?.clearMarks(name);
}

/**
* Indicates whether the performance API is enabled.
*/
Expand Down
12 changes: 9 additions & 3 deletions src/compiler/performanceCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace ts {
export interface Performance {
mark(name: string): void;
measure(name: string, startMark?: string, endMark?: string): void;
clearMeasures(name?: string): void;
clearMarks(name?: string): void;
now(): number;
timeOrigin: number;
}
Expand Down Expand Up @@ -50,6 +52,8 @@ namespace ts {
typeof performance.mark === "function" &&
typeof performance.measure === "function" &&
typeof performance.now === "function" &&
typeof performance.clearMarks === "function" &&
typeof performance.clearMeasures === "function" &&
typeof PerformanceObserver === "function";
}

Expand All @@ -73,8 +77,8 @@ namespace ts {
try {
let performance: Performance;
const { performance: nodePerformance, PerformanceObserver } = require("perf_hooks") as typeof import("perf_hooks");
if (hasRequiredAPI(nodePerformance, PerformanceObserver)) {
performance = nodePerformance;
if (hasRequiredAPI(nodePerformance as unknown as Performance, PerformanceObserver)) {
performance = nodePerformance as unknown as Performance;
// There is a bug in Node's performance.measure prior to 12.16.3/13.13.0 that does not
// match the Web Performance API specification. Node's implementation did not allow
// optional `start` and `end` arguments for `performance.measure`.
Expand All @@ -95,7 +99,9 @@ namespace ts {
if (end === "__performance.measure-fix__") {
nodePerformance.clearMarks("__performance.measure-fix__");
}
}
},
clearMarks(name) { return nodePerformance.clearMarks(name); },
clearMeasures(name) { return (nodePerformance as unknown as Performance).clearMeasures(name); },
};
}
return {
Expand Down
40 changes: 38 additions & 2 deletions src/compiler/tsbuildPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ namespace ts {
return isParsedCommandLine(value) ? value : undefined;
}

performance.mark("SolutionBuilder::beforeConfigFileParsing");
let diagnostic: Diagnostic | undefined;
const { parseConfigFileHost, baseCompilerOptions, baseWatchOptions, extendedConfigCache, host } = state;
let parsed: ParsedCommandLine | undefined;
Expand All @@ -417,6 +418,8 @@ namespace ts {
parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop;
}
configFileCache.set(configFilePath, parsed || diagnostic!);
performance.mark("SolutionBuilder::afterConfigFileParsing");
performance.measure("SolutionBuilder::Config file parsing", "SolutionBuilder::beforeConfigFileParsing", "SolutionBuilder::afterConfigFileParsing");
return parsed;
}

Expand Down Expand Up @@ -734,6 +737,7 @@ namespace ts {
if (updateOutputFileStampsPending) {
updateOutputTimestamps(state, config, projectPath);
}
performance.mark("SolutionBuilder::Timestamps only updates");
return doneInvalidatedProject(state, projectPath);
}
};
Expand Down Expand Up @@ -847,6 +851,8 @@ namespace ts {

function done(cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers) {
executeSteps(BuildStep.Done, cancellationToken, writeFile, customTransformers);
if (kind === InvalidatedProjectKind.Build) performance.mark("SolutionBuilder::Projects built");
else performance.mark("SolutionBuilder::Bundles updated");
return doneInvalidatedProject(state, projectPath);
}

Expand Down Expand Up @@ -1809,7 +1815,10 @@ namespace ts {
return prior;
}

performance.mark("SolutionBuilder::beforeUpToDateCheck");
const actual = getUpToDateStatusWorker(state, project, resolvedPath);
performance.mark("SolutionBuilder::afterUpToDateCheck");
performance.measure("SolutionBuilder::Up-to-date check", "SolutionBuilder::beforeUpToDateCheck", "SolutionBuilder::afterUpToDateCheck");
state.projectStatus.set(resolvedPath, actual);
return actual;
}
Expand Down Expand Up @@ -1958,6 +1967,14 @@ namespace ts {
}

function build(state: SolutionBuilderState, project?: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers, onlyReferences?: boolean): ExitStatus {
performance.mark("SolutionBuilder::beforeBuild");
const result = buildWorker(state, project, cancellationToken, writeFile, getCustomTransformers, onlyReferences);
performance.mark("SolutionBuilder::afterBuild");
performance.measure("SolutionBuilder::Build", "SolutionBuilder::beforeBuild", "SolutionBuilder::afterBuild");
return result;
}

function buildWorker(state: SolutionBuilderState, project: string | undefined, cancellationToken: CancellationToken | undefined, writeFile: WriteFileCallback | undefined, getCustomTransformers: ((project: string) => CustomTransformers) | undefined, onlyReferences: boolean | undefined): ExitStatus {
const buildOrder = getBuildOrderFor(state, project, onlyReferences);
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;

Expand Down Expand Up @@ -1986,7 +2003,15 @@ namespace ts {
: ExitStatus.DiagnosticsPresent_OutputsSkipped;
}

function clean(state: SolutionBuilderState, project?: string, onlyReferences?: boolean) {
function clean(state: SolutionBuilderState, project?: string, onlyReferences?: boolean): ExitStatus {
performance.mark("SolutionBuilder::beforeClean");
const result = cleanWorker(state, project, onlyReferences);
performance.mark("SolutionBuilder::afterClean");
performance.measure("SolutionBuilder::Clean", "SolutionBuilder::beforeClean", "SolutionBuilder::afterClean");
return result;
}

function cleanWorker(state: SolutionBuilderState, project: string | undefined, onlyReferences: boolean | undefined) {
const buildOrder = getBuildOrderFor(state, project, onlyReferences);
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;

Expand Down Expand Up @@ -2063,6 +2088,14 @@ namespace ts {
}

function buildNextInvalidatedProject(state: SolutionBuilderState, changeDetected: boolean) {
performance.mark("SolutionBuilder::beforeBuild");
const buildOrder = buildNextInvalidatedProjectWorker(state, changeDetected);
performance.mark("SolutionBuilder::afterBuild");
performance.measure("SolutionBuilder::Build", "SolutionBuilder::beforeBuild", "SolutionBuilder::afterBuild");
if (buildOrder) reportErrorSummary(state, buildOrder);
}

function buildNextInvalidatedProjectWorker(state: SolutionBuilderState, changeDetected: boolean) {
state.timerToBuildInvalidatedProject = undefined;
if (state.reportFileChangeDetected) {
state.reportFileChangeDetected = false;
Expand Down Expand Up @@ -2092,7 +2125,7 @@ namespace ts {
}
}
disableCache(state);
reportErrorSummary(state, buildOrder);
return buildOrder;
}

function watchConfigFile(state: SolutionBuilderState, resolved: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine | undefined) {
Expand Down Expand Up @@ -2199,6 +2232,7 @@ namespace ts {

function startWatching(state: SolutionBuilderState, buildOrder: AnyBuildOrder) {
if (!state.watchAllProjectsPending) return;
performance.mark("SolutionBuilder::beforeWatcherCreation");
state.watchAllProjectsPending = false;
for (const resolved of getBuildOrderFromAnyBuildOrder(buildOrder)) {
const resolvedPath = toResolvedConfigFilePath(state, resolved);
Expand All @@ -2217,6 +2251,8 @@ namespace ts {
watchPackageJsonFiles(state, resolved, resolvedPath, cfg);
}
}
performance.mark("SolutionBuilder::afterWatcherCreation");
performance.measure("SolutionBuilder::Watcher creation", "SolutionBuilder::beforeWatcherCreation", "SolutionBuilder::afterWatcherCreation");
}

function stopWatching(state: SolutionBuilderState) {
Expand Down
Loading

0 comments on commit b19741c

Please sign in to comment.