perf(ngcc): use EntryPointManifest
to speed up noop ProgramBaseEntryPointFinder
(#37665)
Previously the `ProgramBasedEntryPointFinder` was parsing all the entry-points referenced by the program for dependencies even if all the entry-points had been processed already. Now this entry-point finder will re-use the `EntryPointManifest` to load the entry-point dependencies when possible which avoids having to parse them all again, on every invocation of ngcc. Previously the `EntryPointManifest` was only used in the `DirectoryWalkerEntryPointFinder`, which also contained the logic for computing the contents of the manifest. This logic has been factored out into an `EntryPointCollector` class. Both the `ProgramBasedEntryPointFinder` and `DirectoryWalkerEntryPointFinder` now use the `EntryPointManifest` and the `EntryPointCollector`. The result of this change is that there is a small cost on the first run of ngcc to compute and store the manifest - the processing takes 102% of the processing time before this PR. But on subsequent runs there is a significant benefit on subsequent runs - the processing takes around 50% of the processing time before this PR. PR Close #37665
This commit is contained in:

committed by
Andrew Kushnir

parent
290bc7334d
commit
9318e23e64
@ -14,6 +14,7 @@ import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
||||
import {EsmDependencyHost} from '../../src/dependencies/esm_dependency_host';
|
||||
import {ModuleResolver} from '../../src/dependencies/module_resolver';
|
||||
import {DirectoryWalkerEntryPointFinder} from '../../src/entry_point_finder/directory_walker_entry_point_finder';
|
||||
import {EntryPointCollector} from '../../src/entry_point_finder/entry_point_collector';
|
||||
import {NgccConfiguration, ProcessedNgccPackageConfig} from '../../src/packages/configuration';
|
||||
import {EntryPoint} from '../../src/packages/entry_point';
|
||||
import {EntryPointManifest, EntryPointManifestFile} from '../../src/packages/entry_point_manifest';
|
||||
@ -25,6 +26,7 @@ runInEachFileSystem(() => {
|
||||
let resolver: DependencyResolver;
|
||||
let logger: MockLogger;
|
||||
let config: NgccConfiguration;
|
||||
let collector: EntryPointCollector;
|
||||
let manifest: EntryPointManifest;
|
||||
let _Abs: typeof absoluteFrom;
|
||||
|
||||
@ -37,6 +39,7 @@ runInEachFileSystem(() => {
|
||||
config = new NgccConfiguration(fs, _Abs('/'));
|
||||
resolver = new DependencyResolver(fs, logger, config, {esm2015: srcHost}, dtsHost);
|
||||
manifest = new EntryPointManifest(fs, config, logger);
|
||||
collector = new EntryPointCollector(fs, config, logger, resolver);
|
||||
});
|
||||
|
||||
describe('findEntryPoints()', () => {
|
||||
@ -50,7 +53,7 @@ runInEachFileSystem(() => {
|
||||
...createPackage(fs.resolve(basePath, 'common'), 'testing', ['common']),
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(dumpEntryPointPaths(basePath, entryPoints)).toEqual([
|
||||
['common', 'common'],
|
||||
@ -71,7 +74,7 @@ runInEachFileSystem(() => {
|
||||
...createPackage(fs.resolve(basePath, '@angular/common'), 'testing', ['@angular/common']),
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(dumpEntryPointPaths(basePath, entryPoints)).toEqual([
|
||||
['@angular/common', '@angular/common'],
|
||||
@ -84,7 +87,7 @@ runInEachFileSystem(() => {
|
||||
it('should return an empty array if there are no packages', () => {
|
||||
fs.ensureDir(_Abs('/no_packages/node_modules/should_not_be_found'));
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/no_packages/node_modules'), undefined);
|
||||
logger, resolver, collector, manifest, _Abs('/no_packages/node_modules'), undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(entryPoints).toEqual([]);
|
||||
});
|
||||
@ -97,7 +100,7 @@ runInEachFileSystem(() => {
|
||||
},
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/no_valid_entry_points/node_modules'),
|
||||
logger, resolver, collector, manifest, _Abs('/no_valid_entry_points/node_modules'),
|
||||
undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(entryPoints).toEqual([]);
|
||||
@ -106,7 +109,7 @@ runInEachFileSystem(() => {
|
||||
it('should not include ignored entry-points', () => {
|
||||
const basePath = _Abs('/project/node_modules');
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
|
||||
loadTestFiles(createPackage(basePath, 'some-package'));
|
||||
spyOn(config, 'getPackageConfig')
|
||||
@ -124,7 +127,7 @@ runInEachFileSystem(() => {
|
||||
it('should look for sub-entry-points even if a containing entry-point is ignored', () => {
|
||||
const basePath = _Abs('/project/node_modules');
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
|
||||
loadTestFiles([
|
||||
...createPackage(basePath, 'some-package'),
|
||||
@ -161,7 +164,7 @@ runInEachFileSystem(() => {
|
||||
spyOn(manifest, 'readEntryPointsUsingManifest').and.callThrough();
|
||||
spyOn(manifest, 'writeEntryPointManifest').and.callThrough();
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
finder.findEntryPoints();
|
||||
expect(manifest.readEntryPointsUsingManifest).toHaveBeenCalled();
|
||||
expect(manifest.writeEntryPointManifest).toHaveBeenCalled();
|
||||
@ -182,7 +185,7 @@ runInEachFileSystem(() => {
|
||||
spyOn(manifest, 'readEntryPointsUsingManifest').and.callThrough();
|
||||
spyOn(manifest, 'writeEntryPointManifest').and.callThrough();
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
finder.findEntryPoints();
|
||||
expect(manifest.readEntryPointsUsingManifest).toHaveBeenCalled();
|
||||
expect(manifest.writeEntryPointManifest).toHaveBeenCalled();
|
||||
@ -200,7 +203,7 @@ runInEachFileSystem(() => {
|
||||
{name: _Abs('/sub_entry_points/yarn.lock'), contents: 'MOCK LOCK FILE'},
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
|
||||
// Prime the manifest by calling findEntryPoints() once.
|
||||
finder.findEntryPoints();
|
||||
@ -229,8 +232,7 @@ runInEachFileSystem(() => {
|
||||
...createPackage(_Abs('/dotted_folders/node_modules/'), '.common'),
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/dotted_folders/node_modules'),
|
||||
undefined);
|
||||
logger, resolver, collector, manifest, _Abs('/dotted_folders/node_modules'), undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(entryPoints).toEqual([]);
|
||||
});
|
||||
@ -241,7 +243,7 @@ runInEachFileSystem(() => {
|
||||
_Abs('/external/node_modules/common'), _Abs('/symlinked_folders/node_modules/common'));
|
||||
loadTestFiles(createPackage(_Abs('/external/node_modules'), 'common'));
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/symlinked_folders/node_modules'),
|
||||
logger, resolver, collector, manifest, _Abs('/symlinked_folders/node_modules'),
|
||||
undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(entryPoints).toEqual([]);
|
||||
@ -253,7 +255,7 @@ runInEachFileSystem(() => {
|
||||
...createPackage(_Abs('/nested_node_modules/node_modules/outer/node_modules'), 'inner'),
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/nested_node_modules/node_modules'),
|
||||
logger, resolver, collector, manifest, _Abs('/nested_node_modules/node_modules'),
|
||||
undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
// Note that the `inner` entry-point is not part of the `outer` package
|
||||
@ -272,9 +274,9 @@ runInEachFileSystem(() => {
|
||||
]);
|
||||
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, _Abs('/nested_node_modules/node_modules'),
|
||||
logger, resolver, collector, manifest, _Abs('/nested_node_modules/node_modules'),
|
||||
undefined);
|
||||
const spy = spyOn(finder, 'walkDirectoryForPackages').and.callThrough();
|
||||
const spy = spyOn(collector, 'walkDirectoryForPackages').and.callThrough();
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(spy.calls.allArgs()).toEqual([
|
||||
[_Abs(basePath)],
|
||||
@ -295,8 +297,8 @@ runInEachFileSystem(() => {
|
||||
]);
|
||||
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
const spy = spyOn(finder, 'walkDirectoryForPackages').and.callThrough();
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
const spy = spyOn(collector, 'walkDirectoryForPackages').and.callThrough();
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(spy.calls.allArgs()).toEqual([
|
||||
[_Abs(basePath)],
|
||||
@ -319,8 +321,8 @@ runInEachFileSystem(() => {
|
||||
]);
|
||||
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
const spy = spyOn(finder, 'walkDirectoryForPackages').and.callThrough();
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
const spy = spyOn(collector, 'walkDirectoryForPackages').and.callThrough();
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(spy.calls.allArgs()).toEqual([
|
||||
[_Abs(basePath)],
|
||||
@ -339,7 +341,7 @@ runInEachFileSystem(() => {
|
||||
...createPackage(fs.resolve(basePath, 'package/container'), 'entry-point-1'),
|
||||
]);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, undefined);
|
||||
logger, resolver, collector, manifest, basePath, undefined);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(dumpEntryPointPaths(basePath, entryPoints)).toEqual([
|
||||
['package', 'package'],
|
||||
@ -367,8 +369,9 @@ runInEachFileSystem(() => {
|
||||
const srcHost = new EsmDependencyHost(fs, new ModuleResolver(fs, pathMappings));
|
||||
const dtsHost = new DtsDependencyHost(fs, pathMappings);
|
||||
resolver = new DependencyResolver(fs, logger, config, {esm2015: srcHost}, dtsHost);
|
||||
collector = new EntryPointCollector(fs, config, logger, resolver);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, pathMappings);
|
||||
logger, resolver, collector, manifest, basePath, pathMappings);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(dumpEntryPointPaths(basePath, entryPoints)).toEqual([
|
||||
['pkg1', 'pkg1'],
|
||||
@ -396,7 +399,7 @@ runInEachFileSystem(() => {
|
||||
const dtsHost = new DtsDependencyHost(fs, pathMappings);
|
||||
resolver = new DependencyResolver(fs, logger, config, {esm2015: srcHost}, dtsHost);
|
||||
const finder = new DirectoryWalkerEntryPointFinder(
|
||||
fs, config, logger, resolver, manifest, basePath, pathMappings);
|
||||
logger, resolver, collector, manifest, basePath, pathMappings);
|
||||
const {entryPoints} = finder.findEntryPoints();
|
||||
expect(dumpEntryPointPaths(basePath, entryPoints)).toEqual([
|
||||
['test', 'test'],
|
||||
|
@ -15,6 +15,7 @@ import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
||||
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
||||
import {EsmDependencyHost} from '../../src/dependencies/esm_dependency_host';
|
||||
import {ModuleResolver} from '../../src/dependencies/module_resolver';
|
||||
import {EntryPointCollector} from '../../src/entry_point_finder/entry_point_collector';
|
||||
import {ProgramBasedEntryPointFinder} from '../../src/entry_point_finder/program_based_entry_point_finder';
|
||||
import {NgccConfiguration} from '../../src/packages/configuration';
|
||||
import {EntryPoint} from '../../src/packages/entry_point';
|
||||
@ -68,9 +69,10 @@ runInEachFileSystem(() => {
|
||||
const dtsHost = new DtsDependencyHost(fs);
|
||||
const config = new NgccConfiguration(fs, projectPath);
|
||||
const resolver = new DependencyResolver(fs, logger, config, {esm2015: srcHost}, dtsHost);
|
||||
const collector = new EntryPointCollector(fs, config, logger, resolver);
|
||||
const manifest = new EntryPointManifest(fs, config, logger);
|
||||
return new ProgramBasedEntryPointFinder(
|
||||
fs, config, logger, resolver, basePath, tsConfig, projectPath);
|
||||
fs, config, logger, resolver, collector, manifest, basePath, tsConfig, projectPath);
|
||||
}
|
||||
|
||||
function createProgram(projectPath: AbsoluteFsPath): TestFile[] {
|
||||
|
Reference in New Issue
Block a user