Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs performance issues in $apply, but bindings are fast

I have a medium sized angular app which uses angular-1.2.10 and ui-router-0.2.8. When I transition to a particular state I am getting frame rate issues on the animation regardless of if I am using $animate on a ng-show or manually animating it.

When I dig into the profiler I can see that the $apply after the XHR is taking up to 200ms. Which I am presuming to be the cause of the lag. When I remove the code in the state I am going to, this problem goes as expected. enter image description here

There is no large ng-repeat, and the bindings are fast: enter image description here

This is leaving me a bit stuck as I can't see where the issue is originating from. If anyone can see something to point me in the right direction that would be great.

UPDATE I have done into incoginto mode and run the same tests, with the $digest counter. The $digest runs 40 times and produces the following.enter image description here

Lots of things seem to take a long time(30ms+) but I still can't find a cause.

UPDATE looking at the timeline there seems to be a lot of DOMSubTreeModified.

like image 546
MaxWillmott Avatar asked Jan 12 '23 04:01

MaxWillmott


2 Answers

Angular uses $digest cycles to see if anything needs updating. The pure fact that you've counted a lot is probably just another symptom of potential optimization. The true problem lies in the time it is taking, and the processing bottleneck since it's slowing down animations. So there are a couple of things to try:

  • Make sure you are not deep-watching anything, which means you shouldn't be passing 'true' for objectEquality. This process is more intensive and uses more memory as well.

  • Use isolate scope if directives are involved - if you can. Having an isolate scope will reduce the chatter of $digests in contrast to an inherited scope, since it will re-digest all shared scopes whenever the parent-controller changes.

  • Try replacing $watch statements with an event handler if they are rendered in the DOM. The reason for this is you can reduce the number of times the DOM is re-rendered by $broadcasting an event once the data has been processed (at the end of the XHR call) instead of it re-rendering each time you modify a property.

  • Can you animate via CSS using hardware-accelerated attributes to smooth it out?

like image 93
Matt Pileggi Avatar answered Jan 17 '23 01:01

Matt Pileggi


Multiple $digests means you have cascading model changes, where changing a triggers a $watch('a') that in turn changes b, which triggers another digest that might trigger a $watch('c'), which triggers another digest that might (heaven forbid) trigger a $watch('a').

That cascade can take a long time even if each individual $watch evaluation is fast. If you can do all of your changes in one go without sending them propogating between watches you'll cut down your digest count.

like image 44
Riley Lark Avatar answered Jan 17 '23 02:01

Riley Lark