perf(ngcc): process tasks in parallel in async mode (#32427)

`ngcc` supports both synchronous and asynchronous execution. The default
mode when using `ngcc` programmatically (which is how `@angular/cli` is
using it) is synchronous. When running `ngcc` from the command line
(i.e. via the `ivy-ngcc` script), it runs in async mode.

Previously, the work would be executed in the same way in both modes.

This commit improves the performance of `ngcc` in async mode by
processing tasks in parallel on multiple processes. It uses the Node.js
built-in [`cluster` module](https://nodejs.org/api/cluster.html) to
launch a cluster of Node.js processes and take advantage of multi-core
systems.

Preliminary comparisons indicate a 1.8x to 2.6x speed improvement when
processing the angular.io app (apparently depending on the OS, number of
available cores, system load, etc.). Further investigation is needed to
better understand these numbers and identify potential areas of
improvement.

Inspired by/Based on @alxhub's prototype: alxhub/angular@cb631bdb1
Original design doc: https://hackmd.io/uYG9CJrFQZ-6FtKqpnYJAA?view

Jira issue: [FW-1460](https://angular-team.atlassian.net/browse/FW-1460)

PR Close #32427
This commit is contained in:
George Kalpakas
2019-08-29 18:47:54 +03:00
committed by Matias Niemelä
parent f4e4bb2085
commit e36e6c85ef
17 changed files with 1174 additions and 19 deletions

View File

@ -5,6 +5,11 @@
* 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
*/
/// <reference types="node" />
import * as os from 'os';
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, join} from '../../../src/ngtsc/file_system';
import {Folder, MockFileSystem, TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers';
@ -15,6 +20,7 @@ import {Transformer} from '../../src/packages/transformer';
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
import {MockLogger} from '../helpers/mock_logger';
const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true});
runInEachFileSystem(() => {
@ -28,6 +34,9 @@ runInEachFileSystem(() => {
fs = getFileSystem();
pkgJsonUpdater = new DirectPackageJsonUpdater(fs);
initMockFileSystem(fs, testFiles);
// Force single-process execution in unit tests by mocking available CPUs to 1.
spyOn(os, 'cpus').and.returnValue([{model: 'Mock CPU'}]);
});
it('should run ngcc without errors for esm2015', () => {
@ -402,7 +411,6 @@ runInEachFileSystem(() => {
propertiesToConsider: ['module', 'fesm5', 'esm5'],
compileAllFormats: false,
logger: new MockLogger(),
});
// * In the Angular packages fesm5 and module have the same underlying format,
// so both are marked as compiled.