During profiling of my angularjs application, I found that sometimes $get.Scope.$eval
takes more than 100ms. During the single $digest loop there are at least 3 long cases of $get.Scope.$eval
and I'd like to optimize this part.
Below the $get.Scope.$eval
in profiler I see only invoking of angularjs code.
Here is a screenshot of profile chart.
Could anyone suggest, what's going on and how to optimize this part? I suppose that it can be caused by ng-repeat
, ng-include
or ng-if
, but I'm not sure.
Update:
Here is the simplified structure of my application. Probably, the problem is in the architecture of my application. The app mostly working on the single route and change it only for 3 cases, so application store state in the global controller AppController
- fat controller. Also there are 20k+ nodes in the html and the number can grow(maximum I saw is 60k)
$eval is used internally by angular when resolving angular expressions, such as {{variable}}
. Without seeing any of your code, it's hard to tell what expressions are using resources unnecessarily, but usually too large or nested ng-repeat
s (or many ng-
directives included within an ng-repeat
) are a code smell.
Angular uses dirty checking to evaluate these expressions (for lack of a better option) - that means that every time you create a binding with the {{}}
syntax, it creates an implicit $watch expression getting that value, that will be called every digest cycle to see if the value has changed (on which change the relevant parts of the DOM are regenerated).
Here's one optimization I've used successfully in the past:
most of the time, when you bind a value with {{}}
, you don't actually expect the value to change (like a label), and this 2-way data binding is completely superflous. Since angular version 1.3 you have the options to create one-time bindings with the ::
syntax:
One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value
which eliminates the corresponding performance overhead of such bindings. (If you're using older angular versions, external libraries can mimick this behaviour, such as bindonce.)
Here are some additional tools I've found useful while profiling/optimizing angular apps:
This stackoverflow answer, giving a neat solution for counting how many watch expressions are active on your page. A rule of thumb is that if you're above 2000, you'll start noticing performance issues, and you should think about changing your architecture - employ lazy loading mechanisms, reconsider whether you truly need all the bindings etc.
In production environments disabling the default "debug mode" of angular can also help with performance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With