Skip to content

perf(@angular/build): consolidate build worker pools with shared router - #33909

Open
alan-agius4 wants to merge 1 commit into
angular:mainfrom
alan-agius4:perf-build-singleton-shared-worker-pool
Open

perf(@angular/build): consolidate build worker pools with shared router#33909
alan-agius4 wants to merge 1 commit into
angular:mainfrom
alan-agius4:perf-build-singleton-shared-worker-pool

Conversation

@alan-agius4

@alan-agius4 alan-agius4 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

perf(@angular/build): consolidate build worker pools with shared router

Unify isolated per-subsystem worker pools (JavaScriptTransformer, SassService, I18nInliner) into a single singleton WorkerPool routed via dynamic task dispatching (shared-worker-router.ts).

  • Reduce active worker threads by 66.7% (24 -> 8 threads), eliminating thread thrashing and reducing kernel system CPU time by 42.3%.
  • Implement zero-copy transferable file and translation Blobs, avoiding IPC serialization overhead.
  • Add bounded Map caching (fileDataCache, deserializedTranslations) with fileKey and translationKey in the i18n inliner worker isolate, achieving 100% AST and 99.8% translation cache hit rates across locales without memory leaks.
  • Standardize discriminated union tasks (InlineI18nFileTask, InlineI18nCodeTask) with zero-allocation synchronous dispatching.

Benchmark 1: Subsystem Benchmark (500 Components, 500 SCSS Stylesheets, 5 Locales / 3,500 operations, 5 iterations)

Metric Baseline (main) Consolidated (perf-build-singleton-shared-worker-pool) Delta / Speedup
Active Worker Threads 24 threads 8 threads -66.7% threads (-16 threads)
Cold Build Duration (mean) 1,182.0 ms 1,180.5 ms 1.00x faster (-0.1%)
Cold Build Duration (min / max) 1,151.7 ms / 1,228.2 ms 1,156.8 ms / 1,224.2 ms +5.1 ms / -4.0 ms
P95 Build Latency 1,228.2 ms 1,224.2 ms -0.3% (-4.0 ms)
Throughput 2,962.4 ops/sec 2,966.1 ops/sec +0.1% (+3.7 ops/sec)
I18n Inlining Duration (Pure mean) 696.0 ms 217.9 ms 3.19x faster (-68.7%)
I18n Inlining (min / max) 678.7 ms / 730.5 ms 196.4 ms / 243.2 ms 3.46x / 3.00x faster
AST Cache Hit Rate (Subsequent Locales) 0.0% (0 / 2,000) 100.0% (2,000 / 2,000) 100.0% cache hit rate
Translation Cache Hit Rate 0.0% (0 / 2,500) 99.8% (2,495 / 2,500) 99.8% cache hit rate
Process RSS Delta +2,786.0 MB +1,519.7 MB -45.5% (-1,266.3 MB saved)
Final Process RSS 2,842.1 MB 1,576.4 MB -44.5% (-1,265.7 MB saved)
Kernel System CPU 2,355.1 ms 1,358.3 ms -42.3% (1.73x less kernel CPU)
Total CPU (User + Kernel) 16,198.8 ms 10,808.7 ms -33.3% (1.50x CPU efficiency)

Benchmark 2: End-to-End ng build Application Benchmark (500 Components, 500 SCSS Stylesheets, 5 Locales, 5 iterations)

Metric Baseline (main) Consolidated (perf-build-singleton-shared-worker-pool) Delta / Speedup
Active Worker Threads 24 threads 8 threads -66.7% threads (-16 threads)
E2E Build Duration (mean) 5,267.1 ms 5,651.3 ms +7.3% (+384.2 ms)
E2E Build Duration (min / max) 5,187.5 ms / 5,351.7 ms 5,595.6 ms / 5,737.8 ms +408.1 ms / +386.1 ms
P95 Build Latency 5,351.7 ms 5,737.8 ms +7.2% (+386.1 ms)
Process RSS Delta +2,215.3 MB +2,124.3 MB -4.1% (-91.0 MB saved)
Final Process RSS 2,296.2 MB 2,204.7 MB -4.0% (-91.5 MB saved)
Kernel System CPU 3,087.4 ms 3,000.0 ms -2.8% (1.03x less kernel CPU)
Total CPU (User + Kernel) 19,968.8 ms 17,906.2 ms -10.3% (-2,062.6 ms CPU saved)

Note on Concurrency Bounds: On high-core machines, baseline's 24 unthrottled concurrent threads across 3 independent pools allow concurrent execution of different compiler phases, whereas the consolidated 8-thread singleton enforces strict concurrency bounds, trading ~380 ms wall-clock time for -2.06s lower total CPU work and lower peak memory. This is particularly important for lower-end machines and resource-constrained CI/container environments to avoid severe CPU starvation, thread thrashing, and out-of-memory crashes.

@alan-agius4
alan-agius4 requested a review from clydin August 24, 2026 14:22
@alan-agius4 alan-agius4 added the target: minor This PR is targeted for the next minor release label Aug 24, 2026
@alan-agius4
alan-agius4 removed the request for review from clydin August 24, 2026 14:22
@angular-robot angular-robot Bot added area: performance Issues related to performance area: @angular/build labels Aug 24, 2026
@alan-agius4
alan-agius4 force-pushed the perf-build-singleton-shared-worker-pool branch from ef02f83 to 0be1548 Compare August 24, 2026 14:23
@alan-agius4 alan-agius4 changed the title perf(@angular/build): consolidate build worker pools with shared router and persistent caching perf(@angular/build): consolidate build worker pools with shared router Aug 24, 2026
@alan-agius4

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request consolidates multiple worker pools into a single shared singleton worker pool that routes JavaScript transformation, Sass rendering, and i18n inlining tasks through a central router. While this consolidation improves resource management, a critical performance bug was identified in the i18n inliner worker: using WeakMaps keyed by Blob objects passed across the worker boundary results in a 0% cache hit rate, as structured cloning creates new Blob instances on every task, bypassing the cache entirely.

Comment thread packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts Outdated
@alan-agius4
alan-agius4 force-pushed the perf-build-singleton-shared-worker-pool branch 6 times, most recently from 3223cd7 to 970c127 Compare August 24, 2026 16:10
@alan-agius4
alan-agius4 requested a review from clydin August 24, 2026 17:11
@alan-agius4 alan-agius4 added the action: review The PR is still awaiting reviews from at least one requested reviewer label Aug 24, 2026
@alan-agius4
alan-agius4 marked this pull request as ready for review August 24, 2026 17:11

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a shared build worker pool (getSharedBuildWorkerPool) and a central router (shared-worker-router.ts) to consolidate JS transformation, Sass rendering, and i18n inlining tasks into a single worker pool, optimizing resource usage. It also implements bounded in-memory caches in the i18n inliner worker to prevent unbounded memory growth. The review feedback suggests two improvement opportunities: utilizing the new partitionDiagnostics helper in i18n-inliner.ts to reduce duplication, and simplifying the string escaping logic in i18n-inliner-worker.ts for better readability.

Comment thread packages/angular/build/src/tools/esbuild/i18n-inliner.ts Outdated
Comment thread packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts Outdated
Unify isolated per-subsystem worker pools (JavaScriptTransformer, SassService, I18nInliner) into a single singleton WorkerPool routed via dynamic task dispatching (shared-worker-router.ts).

- Reduce active worker threads by 66.7% (24 -> 8 threads), eliminating thread thrashing and reducing kernel system CPU time by 42.3%.
- Implement zero-copy transferable file and translation Blobs, avoiding IPC serialization overhead.
- Add bounded Map caching (fileDataCache, deserializedTranslations) with fileKey and translationKey in the i18n inliner worker isolate, achieving 100% AST and 99.8% translation cache hit rates across locales without memory leaks.
- Standardize discriminated union tasks (InlineI18nFileTask, InlineI18nCodeTask) with zero-allocation synchronous dispatching.

| Metric | Baseline (`main`) | Consolidated (`perf-build-singleton-shared-worker-pool`) | Delta / Speedup |
| :--- | :--- | :--- | :--- |
| Active Worker Threads | 24 threads | 8 threads | -66.7% threads (-16 threads) |
| Cold Build Duration (mean) | 1,182.0 ms | 1,180.5 ms | 1.00x faster (-0.1%) |
| Cold Build Duration (min / max) | 1,151.7 ms / 1,228.2 ms | 1,156.8 ms / 1,224.2 ms | +5.1 ms / -4.0 ms |
| P95 Build Latency | 1,228.2 ms | 1,224.2 ms | -0.3% (-4.0 ms) |
| Throughput | 2,962.4 ops/sec | 2,966.1 ops/sec | +0.1% (+3.7 ops/sec) |
| I18n Inlining Duration (Pure mean) | 696.0 ms | 217.9 ms | 3.19x faster (-68.7%) |
| I18n Inlining (min / max) | 678.7 ms / 730.5 ms | 196.4 ms / 243.2 ms | 3.46x / 3.00x faster |
| AST Cache Hit Rate (Subsequent Locales) | 0.0% (0 / 2,000) | 100.0% (2,000 / 2,000) | 100.0% cache hit rate |
| Translation Cache Hit Rate | 0.0% (0 / 2,500) | 99.8% (2,495 / 2,500) | 99.8% cache hit rate |
| Process RSS Delta | +2,786.0 MB | +1,519.7 MB | -45.5% (-1,266.3 MB saved) |
| Final Process RSS | 2,842.1 MB | 1,576.4 MB | -44.5% (-1,265.7 MB saved) |
| Kernel System CPU | 2,355.1 ms | 1,358.3 ms | -42.3% (1.73x less kernel CPU) |
| Total CPU (User + Kernel) | 16,198.8 ms | 10,808.7 ms | -33.3% (1.50x CPU efficiency) |

| Metric | Baseline (`main`) | Consolidated (`perf-build-singleton-shared-worker-pool`) | Delta / Speedup |
| :--- | :--- | :--- | :--- |
| Active Worker Threads | 24 threads | 8 threads | -66.7% threads (-16 threads) |
| E2E Build Duration (mean) | 5,267.1 ms | 5,651.3 ms | +7.3% (+384.2 ms) |
| E2E Build Duration (min / max) | 5,187.5 ms / 5,351.7 ms | 5,595.6 ms / 5,737.8 ms | +408.1 ms / +386.1 ms |
| P95 Build Latency | 5,351.7 ms | 5,737.8 ms | +7.2% (+386.1 ms) |
| Process RSS Delta | +2,215.3 MB | +2,124.3 MB | -4.1% (-91.0 MB saved) |
| Final Process RSS | 2,296.2 MB | 2,204.7 MB | -4.0% (-91.5 MB saved) |
| Kernel System CPU | 3,087.4 ms | 3,000.0 ms | -2.8% (1.03x less kernel CPU) |
| Total CPU (User + Kernel) | 19,968.8 ms | 17,906.2 ms | -10.3% (-2,062.6 ms CPU saved) |

> **Note on Concurrency Bounds**: On high-core machines, baseline's 24 unthrottled concurrent threads across 3 independent pools allow concurrent execution of different compiler phases, whereas the consolidated 8-thread singleton enforces strict concurrency bounds, trading ~380 ms wall-clock time for -2.06s lower total CPU work and lower peak memory. This is particularly important for lower-end machines and resource-constrained CI/container environments to avoid severe CPU starvation, thread thrashing, and out-of-memory crashes.
@alan-agius4
alan-agius4 force-pushed the perf-build-singleton-shared-worker-pool branch from 970c127 to 2cf891f Compare August 24, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer area: @angular/build area: performance Issues related to performance target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant