From d7ff9cfa24f35348aec0a534f70eff5dbd835eaf Mon Sep 17 00:00:00 2001 From: Noel Mace Date: Sun, 30 Sep 2018 16:12:14 +0200 Subject: [PATCH 1/5] fix(@angular/cli): capture CPU profile Replace the v8-profiler dependency with v8-profiler-node8 as the first one doesn't support node 8 and 10, and that @angular/cli support only node 8 and 10. --- lib/bootstrap-local.js | 6 +++--- packages/angular/cli/lib/init.ts | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js index 89b707fc1923..064691c7db02 100644 --- a/lib/bootstrap-local.js +++ b/lib/bootstrap-local.js @@ -26,10 +26,10 @@ if (process.env['CODE_COVERAGE'] || process.argv.indexOf('--code-coverage') !== let profiler = null; if (process.env['DEVKIT_PROFILING']) { try { - profiler = require('v8-profiler'); + profiler = require('v8-profiler-node8'); } catch (err) { - throw new Error(`Could not require 'v8-profiler'. You must install it separetely with` + - `'npm install v8-profiler --no-save.\n\nOriginal error:\n\n${err}`); + throw new Error(`Could not require 'v8-profiler-node8'. You must install it separetely with` + + `'npm install v8-profiler-node8 --no-save.\n\nOriginal error:\n\n${err}`); } profiler.startProfiling(); diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index 3a269fcee191..8904e618d30a 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -43,8 +43,16 @@ function _fromPackageJson(cwd?: string) { // Check if we need to profile this CLI run. if (process.env['NG_CLI_PROFILING']) { - const profiler = require('v8-profiler'); // tslint:disable-line:no-implicit-dependencies + let profiler: any = null; + try { + profiler = require('v8-profiler-node8'); // tslint:disable-line:no-implicit-dependencies + } catch (err) { + throw new Error(`Could not require 'v8-profiler-node8'. You must install it separetely with` + + `'npm install v8-profiler-node8 --no-save.\n\nOriginal error:\n\n${err}`); + } + profiler.startProfiling(); + const exitHandler = (options: { cleanup?: boolean, exit?: boolean }) => { if (options.cleanup) { const cpuProfile = profiler.stopProfiling(); From 2a2ff08de2bd728ad4fdd880d2c8c0c2393397f1 Mon Sep 17 00:00:00 2001 From: Noel Mace Date: Sun, 30 Sep 2018 16:14:57 +0200 Subject: [PATCH 2/5] docs(@angular/cli): how to capture a CPU profile Add documentation on how to generate a CPU profile capture. --- packages/angular/cli/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/angular/cli/README.md b/packages/angular/cli/README.md index a55e25895106..a0e74dfcf7e4 100644 --- a/packages/angular/cli/README.md +++ b/packages/angular/cli/README.md @@ -226,6 +226,28 @@ Then you can add breakpoints in `dist/@angular` files. For more informations about Node.js debugging in VS Code, see the related [VS Code Documentation](https://code.visualstudio.com/docs/nodejs/nodejs-debugging). +### CPU Profiling + +In order to investigate performance issues, CPU profiling is often usefull. + +To capture a CPU profiling, you can: +1. install the v8-profiler-node8 dependency: `npm install v8-profiler-node8 --no-save` +1. set the NG_CLI_PROFILING Environment variable to the file name you want: + * on Unix systems (Linux & Mac OS X): ̀`export NG_CLI_PROFILING=my-profile` + * on Windows: ̀̀`setx NG_CLI_PROFILING my-profile` + +Then, just run the ng command on which you want to capture a CPU profile. +You will then obtain a `my-profile.cpuprofile` file in the folder from wich you ran the ng command. + +You can use the Chrome Devtools to process it. To do so: +1. open `chrome://inspect/#devices` in Chrome +1. click on "Open dedicated DevTools for Node" +1. go to the "profiler" tab +1. click on the "Load" button and select the generated .cpuprofile file +1. on the left panel, select the associated file + +In addition to this one, another, more elaborated way to capture a CPU profile using the Chrome Devtools is detailed in https://github.com/angular/angular-cli/issues/8259#issue-269908550. + ## Documentation The documentation for the Angular CLI is located in this repo's [wiki](https://github.com/angular/angular-cli/wiki). From 1e3f87f67f96d6b5b15a46bc3b912604ad236d82 Mon Sep 17 00:00:00 2001 From: Noel Mace Date: Sun, 30 Sep 2018 18:27:25 +0200 Subject: [PATCH 3/5] build: add v8-profiler typings After some refactoring on the angular/cli init, v8-profiler typing is required in order to fix a no-any lint error. --- package.json | 1 + packages/angular/cli/lib/init.ts | 4 +++- yarn.lock | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 545259eeea87..4f7b3f203d4d 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "@types/request": "^2.47.1", "@types/semver": "^5.5.0", "@types/source-map": "0.5.2", + "@types/v8-profiler": "^0.0.5", "@types/webpack": "^4.4.11", "@types/webpack-dev-server": "^3.1.0", "@types/webpack-sources": "^0.1.5", diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index 8904e618d30a..564f0810eb49 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -16,6 +16,8 @@ import { SemVer } from 'semver'; import { Duplex } from 'stream'; import { isWarningEnabled } from '../utilities/config'; +import { Profiler } from 'v8-profiler'; + const packageJson = require('../package.json'); function _fromPackageJson(cwd?: string) { @@ -43,7 +45,7 @@ function _fromPackageJson(cwd?: string) { // Check if we need to profile this CLI run. if (process.env['NG_CLI_PROFILING']) { - let profiler: any = null; + let profiler: Profiler; try { profiler = require('v8-profiler-node8'); // tslint:disable-line:no-implicit-dependencies } catch (err) { diff --git a/yarn.lock b/yarn.lock index cf3b27c5ac46..87321d0e80d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -463,6 +463,12 @@ version "1.0.1" resolved "https://codeload.github.com/quicktype/types-urijs/tar.gz/a23603a04e31e883a92244bff8515e3d841a8b98" +"@types/v8-profiler@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@types/v8-profiler/-/v8-profiler-0.0.5.tgz#2b9f0b7ba3294f5b177b66790607772910a195f9" + dependencies: + "@types/node" "*" + "@types/webpack-dev-server@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.1.0.tgz#1fae06ad346d2dd09bc5e34745723946458eed58" From cac37ebc4fe05dc986af23224dc3472c0db4539a Mon Sep 17 00:00:00 2001 From: Noel Mace Date: Sun, 30 Sep 2018 19:46:58 +0200 Subject: [PATCH 4/5] style: disable no-implicit-dependency v8-profiler We only use @types/v8-profiler, which is a repository dev dependency, and v8-profiler-node8 is a "when needed" dependency. --- packages/angular/cli/lib/init.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index 564f0810eb49..bce12f2cfe0b 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -16,7 +16,8 @@ import { SemVer } from 'semver'; import { Duplex } from 'stream'; import { isWarningEnabled } from '../utilities/config'; -import { Profiler } from 'v8-profiler'; +// from @types/v8-profiler (no dependency to v8-profiler as we use v8-profiler-node8) +import { Profiler } from 'v8-profiler'; // tslint:disable-line:no-implicit-dependencies const packageJson = require('../package.json'); From ec2961c3440a506e82b343ff4bbc3e5e1809ed55 Mon Sep 17 00:00:00 2001 From: Noel Mace Date: Tue, 2 Oct 2018 13:58:44 +0200 Subject: [PATCH 5/5] refactor(@angular/cli): remove v8-profiler typings Remove dependency to the @types/v8-profiler Profiler type as we don't want to depend on it. See https://github.com/angular/angular-cli/pull/12411#discussion_r221688065 --- package.json | 1 - packages/angular/cli/lib/init.ts | 8 ++++---- yarn.lock | 6 ------ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 4f7b3f203d4d..545259eeea87 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "@types/request": "^2.47.1", "@types/semver": "^5.5.0", "@types/source-map": "0.5.2", - "@types/v8-profiler": "^0.0.5", "@types/webpack": "^4.4.11", "@types/webpack-dev-server": "^3.1.0", "@types/webpack-sources": "^0.1.5", diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts index bce12f2cfe0b..41fa2f33e81f 100644 --- a/packages/angular/cli/lib/init.ts +++ b/packages/angular/cli/lib/init.ts @@ -16,9 +16,6 @@ import { SemVer } from 'semver'; import { Duplex } from 'stream'; import { isWarningEnabled } from '../utilities/config'; -// from @types/v8-profiler (no dependency to v8-profiler as we use v8-profiler-node8) -import { Profiler } from 'v8-profiler'; // tslint:disable-line:no-implicit-dependencies - const packageJson = require('../package.json'); function _fromPackageJson(cwd?: string) { @@ -46,7 +43,10 @@ function _fromPackageJson(cwd?: string) { // Check if we need to profile this CLI run. if (process.env['NG_CLI_PROFILING']) { - let profiler: Profiler; + let profiler: { + startProfiling: (name?: string, recsamples?: boolean) => void; + stopProfiling: (name?: string) => any; // tslint:disable-line:no-any + }; try { profiler = require('v8-profiler-node8'); // tslint:disable-line:no-implicit-dependencies } catch (err) { diff --git a/yarn.lock b/yarn.lock index 87321d0e80d2..cf3b27c5ac46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -463,12 +463,6 @@ version "1.0.1" resolved "https://codeload.github.com/quicktype/types-urijs/tar.gz/a23603a04e31e883a92244bff8515e3d841a8b98" -"@types/v8-profiler@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@types/v8-profiler/-/v8-profiler-0.0.5.tgz#2b9f0b7ba3294f5b177b66790607772910a195f9" - dependencies: - "@types/node" "*" - "@types/webpack-dev-server@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.1.0.tgz#1fae06ad346d2dd09bc5e34745723946458eed58"