From bd7f440357d58147f207a9e4daeca156157f9425 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 18 Jun 2020 20:44:48 +0100 Subject: [PATCH] perf(ngcc): shortcircuit tokenizing in ESM dependency host (#37639) This dependency host tokenizes files to identify all the imported paths. This commit calculates the last place in the source code where there can be an import path; it then exits the tokenization when we get to this point in the file. Testing with a reasonably large project showed that the tokenizer spends about 2/3 as much time scanning files. For example in a "noop" hot run of ngcc using the program-based entry-point finder the percentage of time spent in the `scan()` function of the TS tokenizer goes down from 9.9% to 6.6%. PR Close #37639 --- .../ngcc/src/dependencies/esm_dependency_host.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts b/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts index 68890f25c4..7348463c14 100644 --- a/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts +++ b/packages/compiler-cli/ngcc/src/dependencies/esm_dependency_host.ts @@ -47,10 +47,14 @@ export class EsmDependencyHost extends DependencyHostBase { const templateStack: ts.SyntaxKind[] = []; let lastToken: ts.SyntaxKind = ts.SyntaxKind.Unknown; let currentToken: ts.SyntaxKind = ts.SyntaxKind.Unknown; + const stopAtIndex = findLastPossibleImportOrReexport(fileContents); this.scanner.setText(fileContents); while ((currentToken = this.scanner.scan()) !== ts.SyntaxKind.EndOfFileToken) { + if (this.scanner.getTokenPos() > stopAtIndex) { + break; + } switch (currentToken) { case ts.SyntaxKind.TemplateHead: // TemplateHead indicates the beginning of a backticked string @@ -266,6 +270,9 @@ export function hasImportOrReexportStatements(source: string): boolean { return /(?:import|export)[\s\S]+?(["'])(?:\\\1|.)+?\1/.test(source); } +function findLastPossibleImportOrReexport(source: string): number { + return Math.max(source.lastIndexOf('import'), source.lastIndexOf(' from ')); +} /** * Check whether the given statement is an import with a string literal module specifier.