Profiling Angular Change Detection
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
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
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:
- 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.
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.