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!
Related
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.
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.
I know a lot of the big name MVC, M** style JavaScript frameworks allow 2-way binding with Observables.
Meaning if I:
Update a DOM input filed, it will also update a JavaScript object variable which could also save to server with AJAX request.
If I update the JavaScript object variable, it will also in turn update the DOM text field.
As I am learning JavaScript, I would love to skip the big name libraries and learn how to do this in it's most basic raw JavaSript form.
Can anyone provide quick easy to understand demo of this functionality without using libraries like BackboneJS, Knockout, Angular, or others?
jQuery is acceptable.
I would appreciate the lesson and help please.
This is different in every framework.
Angular for instance saves every variable on scopes. Iterate through the scopes variables and compare the values with the previous ones and if there is a change it is carried out to the DOM.
This check is made upon they call digest cycles. If one cycle is finished it calls again until every variable 'observed' is the same as it was in the previous cycle. You can also add objects or vars to this 'observer'.
Angular keeping the view current, with calling this digest every time something could change the 'observed' vars, like http calls, user interactions ... but for instance, if you change a variable outside from angular (console), than the variable change is not carried out to the DOM. You have to call a digest cycle manually to do so.
In HTML5 it is a bit easier with Object.observe, but it is not yet supported in every browser currently on the market.
Hope I could help
Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
Now when I see angular
here is the example:
<div enter="loadMoreTweets()">Roll over to load more tweets</div>
which is from there
http://www.thinkster.io/pick/IgQdYAAt9V/angularjs-directives-talking-to-controllers
which is good style by the tutorial. I dont get it. So then it means earlier example with onclick is also perfectly good? Then why nobody uses it at least these days when people use lot of jquery for example?
Let me cite from a book Angular, by Brad Green & Shyam Seshardi
Chapter 2 ... A Few Words on Unobtrusive JavaScript
The idea of unobtrusive JavaScript has been interpreted many ways, but the rationale
for this style of coding is something along the following lines:
Not everyone’s browser supports JavaScript. Let everyone see all of your content and use your app without needing to execute code in the
browser.
Some folks use browsers that work differently. Visually impaired folks who use screen-readers and some mobile phone users can’t use
sites with JavaScript.
Javascript works differently across different platforms. IE is usually the culprit here. You need to put in different event-handling
code depending on the browser.
These event handlers reference functions in the global namespace. It will cause you headaches when you try to integrate other libraries
with functions of the same names.
These event handlers combine structure and behavior. This makes your code more difficult to maintain, extend, and understand.
In most ways, life was better when you wrote JavaScript in this style.
One thing that was not better, however, was code complexity and
readability. Instead of declaring your event handler actions with the
element they act on, you usually had to assign IDs to these elements,
get a reference to the element, and set up event handlers with
callbacks...
...
In Angular, we decided to reexamine the problem.
The world has changed since these concepts were born...
... for most inline event handlers Angular has an equivalent in the form of
ng-eventhandler="expression" where eventhandler would be replaced by
click, mousedown, change, and so on. If you want to get notified when
a user clicks on an element, you simply use the ng-click directive
like this:
<div ng-click="doSomething()">...</div>
Is your brain saying “No, no, no! Bad, bad, bad!”? The good news is
that you can relax.
These directives differ from their event handler predecessors in that
they:
Behave the same in every browser. Angular takes care of the differences for you.
Do not operate on the global namespace. The expressions you specify can
To get more details, read the book: http://www.amazon.com/AngularJS-Brad-Green/dp/1449344852
EXTEND
Following the discussion in comments, I would like to add a more explanation.
As stated here: Wikipedia - AngularJS:
Angular is a framework, which goal is to augment browser-based applications with model–view–controller (MVC) capability, in an effort to make both development and testing easier
The Model–view–controller, a short extract from wikipedia:
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).
A model notifies its associated views and controllers when there has been a change in its state. This notification allows views to update their presentation, and the controllers to change the available set of commands. In some cases an MVC implementation might instead be "passive," so that other components must poll the model for updates rather than being notified.
A view is told by the controller all the information it needs for generating an output representation to the user. It can also provide generic mechanisms to inform the controller of user input.
Summary:
The most important part here, is the fact, that View can publish the Controllers actions to the user. And this is exactly what the Function calls in HTML do represent.
This is a misunderstanding:
Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
It is perfectly valid to use that style of code if you can decide what event handler to attach to the button when you render the HTML code. With jQuery we see many dynamically attached event handlers because many times the elements themselves are dynamically inserted or whether to attach an event listener or what to attach is dynamically decided.
I know enough jQuery/JavaScript to be dangerous. I have a JSON array that I'm interacting with using two different elements (a calendar and a table, to be precise). Is there an event handler (or any other way) I could bind to so that the table would refresh when the JSON changes?
Basic programming, parse the json (=string) into a javascript object or array. (you probably have already done that.) Use an implementation of the observer patern.
I suggest taking a good look at #Adam Merrifield 's interesting links.
Most of the time using getters and setter where you can fire a custom event (or call a callback method) inside a setter is the key in this.
KnockoutJS is a good framework to help you do such binding. It also uses the observable - observer/subscriber pattern.
using timers is not a really good idea.. little to much overhead. (doing stuff also when nothing gets changed. And you will always hop x ms behind (depending on the polling frequency).
You might want to consider Knockout.JS
It allows bi-directional mapping, so a change to your model should reflect on your view and vice/versa.
http://knockoutjs.com/documentation/json-data.html
However, it might be late stages of your dev cycle, but something to consider.