Profiling Angular Change Detection

Dmitry Mogilko
4 min readDec 27, 2019

Angular Change detection is the central mechanism in the framework and there are a lot of good tutorials describing different strategies to work with and optimize the running times.

However, it took me some time to understand how I can actually get the raw numbers of running times in different situations. Let's examine my findings and also learn a few cool tricks and tools available in Angular!

Measure total time using — ng.profiler tool

First of all, if the Angular application becomes slow we can understand how much time change detection runs on all components by using the ng.profiler tool provided by Angular.

Steps to work with ng.profiler tool are :

1.Enable Angular Debug tools

import {ApplicationRef} from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import {enableDebugTools} from '@angular/platform-browser';

platformBrowserDynamic().bootstrapModule(AppModule).then(moduleRef => {
const applicationRef = moduleRef.injector.get(ApplicationRef);
const componentRef = applicationRef.components[0];
// allows to run `ng.profiler.timeChangeDetection();`
enableDebugTools(componentRef);
}).catch(err => window['console'].error(err));

2. The moment debug tools are enabled we can use it from browser console Open Developer Tools → Console → ng.profiler.timeChangeDetection({record : true})

Result on console

ng.profiler.timeChangeDetection() -Results in Console

According to the Angular source code ng.profiler.timeChangeDetection function :

/** * Exercises change detection in a loop and then prints the average amount of * time in milliseconds how long a single round of change detection takes for * the current state of the UI. It runs a minimum of 5 rounds for a minimum * of 500 milliseconds. * * Optionally, a user may pass a `config` parameter containing a map of * options. Supported options are: * * `record` (boolean) — causes the profiler to record a CPU profile while * it exercises the change detector. Example: * * ``` * ng.profiler.timeChangeDetection({record: true}) * ``` */

Parameter {record: true} will generate CPU profile in JavaScript Profiler tab

CPU profile example

Measure change detection run for a single component

Let me please start by explaining the use case and why we need it.

Recently I was asked to look on an application where UI started to be very slow and unresponsive. I used ng.profiler.timeChangeDetection() as described previously and saw that change detection takes a few seconds on all component tree.

But unfortunately, this was only half of the road. How do I understand which operation causes the long run? The application had a lot of business logic inside and a lot of components loaded …

We can isolate our tests to a specific component by doing the following steps:

  1. We will monkey patch method called tick on ApplicationRef class to be able to measure every change detection run.

About function

import { BrowserModule } from '@angular/platform-browser';
import {ApplicationRef, NgModule} from '@angular/core';
import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(applicationRef: ApplicationRef) {
const originalTick = applicationRef.tick;
applicationRef.tick = function() {
const windowPerfomance = window.performance;
const before = windowPerfomance.now();
const retValue = originalTick.apply(this, arguments);
const after = windowPerfomance.now();
const runTime = after - before;
window.console.log('CHANGE DETECTION TIME' , runTime);
return retValue;
};

}
}

2. In order to run the change detection on a single component, we will use the tool provided by Angular called: ng.probe also available from the browser console.

How to use :

Inspect Element on component in Chrome Dev tools → and than type in Console

ng.probe($0).injector.get(ng.coreTokens.ApplicationRef).tick()

This will trigger change detection on the component and as a result, our intercepted function tick will print the time it takes to run on a specific component.

Run the change detection on a single component

The source for this article is available here: https://github.com/dimaxweb/angular-change-detection-playground

Thank you for reading! If this information was useful please make a clap — this is very important to me.

--

--