From 8e5567d964666526db6a24948bc3f65150869b59 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Sun, 4 Aug 2019 18:31:10 +0300 Subject: [PATCH] perf(ivy): ngcc - avoid unnecessary operations when we only need one format processed (#32003) Previously, when `ngcc` was called with `compileAllFormats === false` (i.e. how `@angular/cli` calls it), it would not attempt to process more properties, once the first was successfully processed. However, it _would_ continue looping over them and perform some unnecessary operations, such as: - Determining the format each property maps to (which can be an expensive operation for some properties mapping to either UMD or CommonJS). - Checking whether each property has been processed (which involves checking whether any property has been processed with a different version of `ngcc` each time). - Potentially marking properties as processed (which involves a file-write operation). This commit avoids the unnecessary operations by entirely skipping subsequent properties, once the first one has been successfully processed. While this theoretically improves performance, it is not expected to have any noticeable impact in practice, since the list of `propertiesToConsider` is typically small and the most expensive operation (marking a property as processed) has low likelihood of happening (plus these operations are a tiny fraction of `ngcc`'s work). PR Close #32003 --- packages/compiler-cli/ngcc/src/main.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/compiler-cli/ngcc/src/main.ts b/packages/compiler-cli/ngcc/src/main.ts index 35a8b8f4ac..9b4af20222 100644 --- a/packages/compiler-cli/ngcc/src/main.ts +++ b/packages/compiler-cli/ngcc/src/main.ts @@ -108,9 +108,12 @@ export function mainNgcc( const entryPointPackageJson = entryPoint.packageJson; const entryPointPackageJsonPath = fileSystem.resolve(entryPoint.path, 'package.json'); - const hasProcessedDts = hasBeenProcessed(entryPointPackageJson, 'typings'); + let processDts = !hasBeenProcessed(entryPointPackageJson, 'typings'); for (const property of propertiesToConsider as EntryPointJsonProperty[]) { + // If we only need one format processed and we already have one, exit the loop. + if (!compileAllFormats && (compiledFormats.size > 0)) break; + const formatPath = entryPointPackageJson[property]; const format = getEntryPointFormat(fileSystem, entryPoint, property); @@ -124,12 +127,10 @@ export function mainNgcc( continue; } - const isFirstFormat = compiledFormats.size === 0; - const processDts = !hasProcessedDts && isFirstFormat; // We don't break if this if statement fails because we still want to mark // the property as processed even if its underlying format has been built already. - if (!compiledFormats.has(formatPath) && (compileAllFormats || isFirstFormat)) { + if (!compiledFormats.has(formatPath)) { const bundle = makeEntryPointBundle( fileSystem, entryPoint, formatPath, isCore, property, format, processDts, pathMappings, true); @@ -148,7 +149,10 @@ export function mainNgcc( // previous property. if (compiledFormats.has(formatPath)) { const propsToMarkAsProcessed = [property]; - if (processDts) propsToMarkAsProcessed.push('typings'); + if (processDts) { + propsToMarkAsProcessed.push('typings'); + processDts = false; + } markAsProcessed( fileSystem, entryPointPackageJson, entryPointPackageJsonPath, propsToMarkAsProcessed);