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-repeats (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:
Batarang, a chrome extension "for debugging and profiling angular applications"
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.
Related
As you know, for the sake of good performance, we always try to minimize rendering in single page applications. For instance, in React whenever a state or props change inside a component, that change make that component re execute, re evaluate and finally re render.
So, are there any similar conditions in Angular ? and what are the best practices and patterns for reducing extra rendering ?
This is a huge topic to cover here but I would suggest the following article for starters: https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
TLDR;
What happens is that Angular at startup time will patch several low-level browser APIs, such as for example addEventListener, which is the browser function used to register all browser events, including click handlers. Angular will replace addEventListener with a new version
So by extending base functionality, angular understands changes that trigger re-evaluation of values and rerendering needs.
As an extra, we need to mention that the comparisons are not deep inside reference types, so some handling should happen.
In the article, several methods for performance tweaking are mentioned like
On push change detection method.
Disabling automatic detection for a component and triggering the cycles manually.
Using immutable objects with the help of libraries line immutable.js
As you can understand, these being their own pitfalls and considerations
My app seems to have views with a lot of logic in them. My question is two fold:
Does logic in the view slow down angular app performance?
As a best practice, is it better to treat this logic in the controller and just store the outcome in a $scope attribute which the view can access ?
Would this improve performance ?
Example of views in our app (a simple one):
<div class="small-12 column" id="notificationMsg">
{{ config.message | translate : config.getMessageParams(notification)}}
</div>
short answer:
yes
long answer:
your bindings will have to be updated in every digest cycle which affects the used variables.
storing the value in a variable and only updating it if something changes will improve your performance.
however this will only be critical if you reach a certain amount of complexity. as long as your app doesn't grow too much this won't be a threat to think about - yet.
i wouldn't necessarily call it a best practice, because it can make your code more complex and harder to read/understand/maintain.
performance isn't always an issue. it just starts to be one as soon as it's absent by default ;)
a further improvement you can do is use ng-bind and ng-bind html instead whenever possible, because it can be rendered faster, since it can skip some internal steps of angularJS whilst compiling the expression.
so e.g. use
<div ng-bind="foo"></div>
instead of
<div>{{ foo }}</div>
if possible
The key concept behind these performance considerations is reducing the number of $$watchers inside Angular to improve the $digest cycle’s performance, something you’ll see and hear more of as you continue working with Angular. These are crucial to keeping our application state fast and responsive for the user. Each time a Model is updated, either through user input in the View, or via service input to the Controller, Angular runs something called a $digest cycle.
This cycle is an internal execution loop that runs through your entire application’s bindings and checks if any values have changed. If values have changed, Angular will also update any values in the Model to return to a clear internal state. When we create data-bindings with AngularJS, we’re creating more $$watchers and $scope Objects, which in turn will take longer to process on each $digest. As we scale our applications, we need to be mindful of how many scopes and bindings we create, as these all add up quickly - each one being checked per $digest loop.
Angular runs every single filter twice per $digest cycle once something has changed. This is some pretty heavy lifting. The first run is from the $$watchers detecting any changes, the second run is to see if there are further changes that need updated values.
Here’s an example of a DOM filter, these are the slowest type of filter, preprocessing our data would be much faster. If you can, avoid the inline filter syntax.
{{ filter_expression | filter : expression : comparator }}
Angular includes a $filter provider, which you can use to run filters in your JavaScript before parsing into the DOM. This will preprocess our data before sending it to the View, which avoids the step of parsing the DOM and understanding the inline filter syntax.
$filter('filter')(array, expression, comparator);
Yes, for better performance, Use
$scope.description: $translate.instant('DESCRIPTION')
in Controller, instead of,
{{'DESCRIPTION' | translate }}
Furthermore,
It depends on what you want to achieve. Here is another way to increase performance.
One Time Binding
Angular 1.3 added :: notation to allow one time binding. In summary, Angular will wait for a value to stabilize after it’s first series of digest cycles, and will use that value to render the DOM element. After that, Angular will remove the watcher forgetting about that binding.
Recently I've walked through several StackOverflow questions related to AngularJS optimization techniques:
AngularJS really slow at rendering with about 2000 elements?
How does data binding work in AngularJS?
Most of the answers were proposing an optimization technique called One-time binding, but my use case dictates that I can't use this approach, all of my data is interactive, the changes are pushed from server to client, plus there's quite a lot of data is required to be displayed. When server notification happens UI updates are required. So if I were to use the one-time binding it would break my page.
I've tried to analyse the reasons that make AngularJS slow in my case and I've found out that it's not the dirty checking itself that is slowing down the process. Modern javascript engines are able to dirty check tens of thousands object properties in just milliseconds. The root reason that make AngularJS slow is $watch expression itself, each $watch call is backed up with setTimeout calls plus some AngularJS internal overhead. The main problem is that these calls pass control to browser's internal message loop, which from program's perspective does nothing except imposing latency into each step of data displaying process.
So my question is the following: in contrast to one-time binding, I would like to have a way to group my one way binding expressions {{ someObj.someProperty }} into one $watch call, something like
{{ myBulkWatch::someObj.someProperty1 }}
{{ myBulkWatch::someObj.someProperty2 }}
...
{{ myBulkWatch::someObj.somePropertyN }}
I understand that there's no such functionality yet, but maybe it's possible to at least emulate the feature with existing Angular's instruments?
Any thoughts on this subject?
Thank you in advance!
I am working on a project targeting mainly mobile devices.
The app receives a list of different objects from the server which shall be rendered all at once.
Each object type has it's own directive, which takes care of business logic. But because most objects share certain features we created 'sub-directives' which work as mixins to keep it DRY.
If more than just a handful of those objects should be displayed (which is the default case), Angular takes quite some time parsing and instantiating those directives + sub-directives.
Our performance improvements so far:
replaced the ng-repeat with a custom directive, which also works like an infinite-scroll
use bindonce to limit bindings only where they are really necessary
pre-fill the $templateCache with the templates, instead of fetching
them via templateUrl
But even with those improvements, the performance is still not acceptable. (Especially when navigating to the state containing the list)
The approach I have in mind now is as follows:
let Angular fully parse and create one such directive with its
sub-directives
cache the resulting node
if we have another object of the same type simple reuse it and link it with a new Scope
But even after going through Angulars source code I have no clue where I could hook in to receive the finished result before advancing to the next object in the list.
So far it parses the template of the actual directive for each entry in the list, then comes back and finishes the sub-directives.
Hope I was able to make it understandable what I am trying to accomplish.
Thanks in advance!
I'm working within a Javascript + BackboneJS (an MVC framework) + RequireJS framework, but this question is somewhat OO generic.
Let me start by explaining that in Backbone, your Views are a mix of traditional Views and Controllers, and your HTML Templates are the traditional MVC Views
Been racking my head about this for a while and I'm not sure what the right/pragmatic approach should be.
I have a User object that contains user preferences (like unit system, language selection, anything else) that a lot of code depends on.
Some of my Views do most of the work without the use of templates (by using 3rd party libs, like Mapping and Graphing libs), and as such they have a dependency on the User object to take care of unit conversion, for example. I'm currently using RequireJS to manage that dependency without breaking encapsulation too much.
Some of my Views do very little work themselves, and only pass on Model data to my templating engine / templates, which do the work and DO have a dependency on the User object, again, for things like units conversion. The only way to pass this dependency into the template is by injecting it into the Model, and passing the model into the template engine.
My question is, how to best handle such a widely needed dependency?
- Create an App-wide reference/global object that is accessible everywhere? (YUK)
- Use RequireJS managed dependencies, even though it's generally only recommended to use managed dependency loading for class/object definitions rather than concrete objects.
- Or, only ever use dependency injection, and manually pass that dependency into everything that needs it?
From a purely technical point of view, I would argue that commutable globals (globals that may change), especially in javascript, are dangerous and wrong. Especially since javascript is full of parts of code that get executed asynchronously. Consider the following code:
window.loggedinuser = Users.get("Paul");
addSomeStuffToLoggedinUser();
window.loggedinuser = Users.get("Sam");
doSomeOtherStuffToLoggedinUser();
Now if addSomeStuffToLoggedinUser() executes asynchronously somewhere (e.g. it does an ajax call, and then another ajax call when the first one finishes), it may very well be adding stuff to the new loggedinuser ("Sam"), by the time it gets to the second ajax call. Clearly not what you want.
Having said that, I'm even less of a supporter of having some user object that we hand around all the time from function to function, ad infinitum.
Personally, having to choose between these two evils, I would choose a global scope for things that "very rarely change" --- unless perhaps I was building a nuclear powerstation or something. So, I tend to make the logged in user available globally in my app, taking the risk that if somehow for some reason some call runs very late, and I have a situation where one user logs out and directly the other one logs in, something strange may happen. (then again, if a meteor crashes into the datacenter that hosts my app, something strange may happen as well... I'm not protecting against that either). Actually a possible solution would be to reload the whole app as soon as someone logs out.
So, I guess it all depends on your app. One thing that makes it better (and makes you feel like you're still getting some OO karma points) is to hide your data in some namespaced singleton:
var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
doSomethingCoolWith(myuser);
in stead of
doSomethingCoolWith(window.loggedinuser);
although it's pretty much the same thing in the end...
I think you already answered your own question, you just want someone else to say it for you : ) Use DI, but you aren't really "manually" passing that dependency into everything since you need to reference it to use it anyways.
Considering the TDD approach, how would you test this? DI is best for a new project, but JS gives you flexible options to deal with concrete global dependencies when testing, ie: context construction. Going way back, Yahoo laid out a module pattern where all modules were loosely coupled and not dependent on each other, but that it was ok to have global context. That global context can make your app construction more pragmatic for things that are constantly reused. Its just that you need to apply that judiciously/sparingly and there need be very strong cases for those things being dynamic.