angular: Performance - Too many digest calls in a ng4/ng1 upgrade hybrid app

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

A digest call is triggered every time the angular’s zone settles. The app I’m working on has an array of 50 largish objects in an ng-repeat. This causes significant degradation in page performance. Even scrolling is affected since it triggers zone updates and, consequently, a digest. I agree that one of the places to look into is fixing the data itself. But the point is, it’s smooth sailing on angular 1.6, while it’s jittery as hell when angular 4 is introduced via upgrade. Here’s some data from google’s angular js plugins.

With angular 4 upgrade module: image

Without angular 4 upgrade module: image

Both the screengrabs above were done while scrolling. The page did not have any custom components or behaviour (like virtual scroll, infinite loading) that is dependent on or directly affects scrolling. I understand why this is happening. I’m not sure if I understand whether it should. I found adding a debounce function to the code which triggers digest on zone settlement yielded a good improvement (~6 digests/second) and the performance drop wasn’t noticeable.

Expected behaviour

I propose that we allow specification of debounce time in arguments of UpgradeModule.bootstrap method. This will be used to make sure that digest is triggered at most once in this frame. I can do a PR if that sounds okay.

Minimal reproduction of the problem with instructions

This is really dependent on the app itself. I did not have success trying to recreate this because I was lacking the complexity/dataset needed for this to happen.

Environment


Angular version: 4.4.0-RC.0 / 1.6.2

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 16 (6 by maintainers)

Most upvoted comments

@gkalpak Just wanna update this ticket about downgradeModule working perfectly. I finally got time to remove that hacky code I put in to unsubscribe observables.

On 5.x, you can use the new downgradeModule() API, which is an alternative to UpgradeModule and drops this “Angular zone”<->“$digest” wiring (and also bootstraps AngularJS outside the Angular zone), which results in much fewer change detection cycles.

The downgradeModule API, which can prevent enormous number of $digest calls in an Upgraded application.

Indeed if you have a listener for scroll events (registered inside the Angular zone), it will trigger a micro task (and subsequently an onMicrotaskEmpty emission and finally a $digest).

This ensures that the two change detections are wired together and changes propagate across the frameworks, but it does create a few more change detection cycles (on both frameworks).

Apart from blacklisting it, as @JiaLiPassion suggested, you have a couple more options:

  1. If you control the code that registers the scroll event listener and you can run it outside the Angular zone:

    constructor(elemRef: ElementRef, ngZone: NgZone) {
      ngZone.runOutsideAngular(() => elemRef.nativeElement.addEventListener('scroll', ...));
    }
    
  2. On 5.x, you can use the new downgradeModule() API, which is an alternative to UpgradeModule and drops this “Angular zone”<->“$digest” wiring (and also bootstraps AngularJS outside the Angular zone), which results in much fewer change detection cycles. (Docs are still work in progress (on #18487), but you can get a preview here.)

In the future, we might indeed make such things configurable, similar to how you sugested, but haven’t decided on the API yet. You might want to wait before starting to work on a PR, but it is great to hear you are interested 😃

@gkalpak time to refactor 😃

well, we upgraded to 5.2.11 like in 10 minutes. we are trying 6.x now.

It did make it into 5.0.0. (E.g. look for downgradeModule() here.) The docs haven’t landed yet, but I am finishing up the PR (#18487) right now.