Skip to content

Commit 46185ce

Browse files
committed
fix(@angular/build): aggregate parallel worker performance timings on the main thread
Rather than having the parallel worker thread print its cumulative durations separately to the console (which causes console spam and disjointed/incomplete final logs), we serialize and return the worker's durations to the main thread upon completing the diagnostics task. The main thread then merges them into the global cumulative durations map, producing a single, complete, and perfectly aggregated performance report at the end of the build. (cherry picked from commit 851711b)
1 parent 38d26a6 commit 46185ce

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

packages/angular/build/src/tools/angular/compilation/parallel-compilation.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { createRequire } from 'node:module';
1212
import { MessageChannel } from 'node:worker_threads';
1313
import type { SourceFile } from 'typescript';
1414
import { WorkerPool } from '../../../utils/worker-pool';
15+
import { mergeCumulativeDurations } from '../../esbuild/profiling';
1516
import type { AngularHostOptions } from '../angular-host';
1617
import { AngularCompilation, DiagnosticModes, EmitFileResult } from './angular-compilation';
1718

@@ -124,10 +125,15 @@ export class ParallelCompilation extends AngularCompilation {
124125
throw new Error('Not implemented in ParallelCompilation.');
125126
}
126127

127-
override diagnoseFiles(
128+
override async diagnoseFiles(
128129
modes = DiagnosticModes.All,
129130
): Promise<{ errors?: PartialMessage[]; warnings?: PartialMessage[] }> {
130-
return this.#worker.run(modes, { name: 'diagnose' });
131+
const { timings, ...result } = await this.#worker.run(modes, { name: 'diagnose' });
132+
if (timings) {
133+
mergeCumulativeDurations(timings);
134+
}
135+
136+
return result;
131137
}
132138

133139
override emitAffectedFiles(): Promise<Iterable<EmitFileResult>> {

packages/angular/build/src/tools/angular/compilation/parallel-worker.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import assert from 'node:assert';
1111
import { randomUUID } from 'node:crypto';
1212
import { type MessagePort, receiveMessageOnPort } from 'node:worker_threads';
1313
import { SourceFileCache } from '../../esbuild/angular/source-file-cache';
14+
import { getAndClearCumulativeDurations } from '../../esbuild/profiling';
1415
import type { AngularCompilation, DiagnosticModes } from './angular-compilation';
1516
import { AotCompilation } from './aot-compilation';
1617
import { JitCompilation } from './jit-compilation';
@@ -121,12 +122,17 @@ export async function initialize(request: InitRequest) {
121122
export async function diagnose(modes: DiagnosticModes): Promise<{
122123
errors?: PartialMessage[];
123124
warnings?: PartialMessage[];
125+
timings?: Record<string, number[]>;
124126
}> {
125127
assert(compilation);
126128

127129
const diagnostics = await compilation.diagnoseFiles(modes);
130+
const timings = getAndClearCumulativeDurations();
128131

129-
return diagnostics;
132+
return {
133+
...diagnostics,
134+
timings,
135+
};
130136
}
131137

132138
export async function emit() {

packages/angular/build/src/tools/esbuild/profiling.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,32 @@ export function resetCumulativeDurations(): void {
1414
cumulativeDurations?.clear();
1515
}
1616

17+
export function getAndClearCumulativeDurations(): Record<string, number[]> | undefined {
18+
if (!cumulativeDurations || cumulativeDurations.size === 0) {
19+
return undefined;
20+
}
21+
22+
const data = Object.fromEntries(cumulativeDurations);
23+
24+
cumulativeDurations.clear();
25+
26+
return data;
27+
}
28+
29+
export function mergeCumulativeDurations(data: Record<string, number[]>): void {
30+
cumulativeDurations ??= new Map();
31+
32+
for (const [name, durations] of Object.entries(data)) {
33+
let existing = cumulativeDurations.get(name);
34+
if (!existing) {
35+
existing = [];
36+
cumulativeDurations.set(name, existing);
37+
}
38+
39+
existing.push(...durations);
40+
}
41+
}
42+
1743
export function logCumulativeDurations(): void {
1844
if (!debugPerformance || !cumulativeDurations) {
1945
return;

0 commit comments

Comments
 (0)