I have an application where I have to draw a lot of small nvd3 charts inside a jqgrid table in my angular application. I am compiling the charts with $compile. However, I notice that the performance is getting slower as the number of data is increasing (it still takes pretty quick to draw 1 small chart, but to wait for the whole thing it takes a really long time)
I noticed that this is a known issue based on this post since it's DOM manipulation. I tried several tricks like compiling the charts in turn, etc, but it still feels so slow. Is there a known workaround for this issue?
I found a way to improve the performance. I am posting this to help other people that have same problem with me.
The problem is:
I made each nvd3 chart as small reusable component as angular directive, and as a result I need to call $compile when I draw it inside jqgrid.
$compile is really not the fastest method out there so removing $compile call and using <svg></svg> directly in jqgrid solves my problem.
So if you have performance problem and you're calling $compile, maybe the first thing to do is to remove that $compile call. I am pretty new to Angular so hope this helps others that are having same prob.
Related
I am working on big application built using angular. I have read a lot articles how to improve performance.
I have implemented below mentioned things -
Avoid Watchers
ng-repeat with track by
single binding
Used ng-if instead of ng-show
used $compileProvider.debugInfoEnabled(false) to remove ng-binding and ng-scope classes in production.
But I have tried a lot plugin but not able to get satisfactory result.
Could anybody tell me how to measure performance of angular app ??
I haven't tried it yet, but it looks promising: https://opbeat.com/angularjs
Other ideas:
Check how many watchers do you have: https://github.com/bahmutov/code-snippets/blob/master/ng-count-watchers.js
Check for memory leaks: http://www.dwmkerr.com/fixing-memory-leaks-in-angularjs-applications
I've made a stripped down fiddle, and you'll have to interact with the map to see the issue:
JSFiddle Link
You'll notice, or at least I hope you will, that if you make a quick drag, the map seems to flash completely gray for an instant. It does not happen every time, so you may have to quickly drag several times to see this. Furthermore, it seems to happen more frequently at lower zoom levels.
This is after the tiles have been cached, so it's not google maps fetching the tiles that causes this. Furthermore, I've tested the behavior on a standard google maps example and it does not cause this flicker. I think it may have something to do with $scope.$apply() being called from the directive and forcing a repaint, because I notice sometimes that the flicker happens while google is loading the tiles, i.e. the two events happen independently of one another.
While my last resort is to dig into the directive, this seems like a pretty fundamental problem from a UX standpoint, and I suspect that some of you must have run into this issue. Perhaps most importantly, the example at
http://angular-ui.github.io/angular-google-maps/#!/demo does not suffer from this issue, though they have set a minimum zoom level, and so I wonder if this is simply a cheap fix for the issue I'm describing.
Thank you for any help you can offer, I've been tearing my app apart at the seams all day trying to pinpoint what's happening, and any advice would be greatly appreciated.
why does stack overflow require a code-line for a jsfiddle link? seems totally contrary to the point of making a fiddle...
I started using ng-grid, and honestly seems it's not easy to tame that beast. I'm having various problems and this is one of them. I'm using ui-router and before ng-grid I was using my own implementation based on ng-repeat and haven't encountered this, so I'm assuming somehow ng-grid is responsible.
So I have a few tabs and ui-view with a grid underneath. Everytime you switch a tab, controller initiates a request and fetches data for the grid. Very first time when you open the app, everything seems to be fine, but whenever you switch to a different tab, for a few milliseconds it shows ugly, unbound content.
I tried to hide grid with ng-if, ng-hide and ng-show - (data.length <= 0), but that didn't work. I tried to place a few $timeout functions, that didn't help either.
Any ideas how to fix that?
UPD: first time when I posted this question I thought what if I make the grid transparent and then change opacity after it gets the data. So it kinda did the trick.
jQuery.animate({opacity:1})
and then I deleted the question, but soon I realized this is not very good way to solve the problem - not very anguleresque. Question remains open.
UPD: Had to abandon ng-grid and currently looking for something better. ng-grid in its current state is horrible. It's painfully slow, full of strange bugs and pretty much useless. Version 3 if far from being ready, and current version is abandoned. Very, very sad.
Actually after using ng-grid for awhile, I have to admit - it's really, really bad. Anyone who values own time and nerves should stay away from it. In its current state project is completely broken, have tons of bugs and authors won't even accept any tickets. They all working hard on a new version and honestly God knows when they ship it. So, for your own sake DON'T use it! I mean I believe in this product and that team. After all those guys gave us awesome ui-router and amazing angular-ui directives. Check the date, who knows maybe this answer already is obsolte and by the time you run across this post all the problems in ng-grid are already solved. But simple fact still remains - the product was so bad, they even decided to rename it.
For now I switched to ux-angularjs-datagrid. It may not be a complete grid solution and doesn't have a cool name and many features you're gonna have to build yourself, but it's amazingly fast and responsive.
We got an app written in AngularJS but we have run into performance issues as the app tries to load a large amount of data from the server and lets the user play around with it (read a complex DOM). Surfing around and reading about it seems that two-way data binding, intrinsically called $watch expressions etc of AngularJS is posing a problem that we are unable to surmount. And then we have come across fb's ReactJS that promises fast view rendering.
This has set us wondering if ReactJS could be used with AngularJS to just take care of the 'view' part. Would be very grateful if anyone could provide some insight or direction regarding this?
Thanks
This tool (single-spa, a javascript framework for front-end microservices) allows you to use different libraries and frameworks combine. In this way, you can save your old business logic.
Have you tried ngReact? I haven't tried it myself but it seems to do what you want (using React components in Angular).
i'm playing with that now to combine angular directives with react, but for my app in pure angular on large data set, i used angulars for $compile and rendering and it works pretty fast, but data manipulation and whole building of this part of HTML is done by d3.js, maybe you can look on that lib...
I'm using AngularJS 1.0.8.
The problem: I have a dynamic website that can be built from various components, or widgets: paragraphs, text blocks, images, hyperlinks, and tables, for that matter.
A paragraph is a container of more components. A table is also a kind of a container - it can hold other components, and it arranges them as a datagrid.
The website is not static, i.e. I don't have a pre-defined layout of such components.
Instead, I get a JSON in startup, that specifies the layout of the components.
Originally, I had a directive of each such component, using templates for that directives, and occasionally using $compile to change the DOM a bit for more complex components.
For the 'container' components - paragraphs and tables - I used ngRepeat to render all of the components that are contained in that container-component.
That was problematic performance-wise. It would take the website many seconds to load on Chrome/Firefox, with the time spent mainly in the AngularJS render mechanism (not in IO, I figured).
So I decided to change the directives of these components. Instead of using ngRepeat, which is not really necessary since I don't need the two-way binding (the content in the website is not interactive and cannot be changed, so really I only need to render it once, very much like a servlet) - I built the HTML string in the directive myself, using plain JS, iterating over all of the contained components that exist in the model, and at the end I $compiled and linked it.
The result wasn't good enough again.
For a table of a few hundered cells, it took ~500 milis to link in modern Chrome/Firefox, and ~4000 milis in IE9, and ~15000 milis in IE8, and IE7 is still rendering so I can't give you the time :)
I thought that the problem might be with an extensive use of directives.
A simple:
<div my-table-component data="data"></div>
element would result, after the link, in a <table> tag with 30-40 <tr> tags, each with 10 <td> tags, and in each there would be an additional <div my-text-component> or <div my-image-component> that would then have to be compiled and linked by itself (since it has a directive).
I though that since my website is not interactive to begin with, I don't really need this.
Maybe I could avoid using directives for each component, and leave only a directive for the container-components. In these directives, I would create the actual HTML template of every possible other component, instead of using directives that would do that.
That takes me another step away from the AngularJS idea towards a servlet idea. And it kind of sucks.
So maybe one of you can offer a better approach for me... Maybe the performance problem is not even there? Maybe a use of directives (and hopefully ngRepeat) can be fine performance-wise even with this amount of items? Maybe there's a better way to make an insightful performance benchmark, other than using Chrome's Developer Tools, Firebug, and Chrome's Batarang AngularJS extension (none of them really directed me in a productive way).
Using a lot of nested directives by itself is not a problem, but any extensive binding could have huge impacts.
If someone is still looking for an aswer to this, using Angular 1.3+, OP could solve his problem by first using one-time binding on all the elements on which he says there is "no need for two-ways bindings", using the ::binding syntax.
In addition, I would suggest trying to spot which bindings exactly are being particularly slow, using the amazing profiling snippets from this website: http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html
Finally, what often takes most time in Angular, especially while building big ng-repeated tables, is the compilation phase. So if possible try to only build a restricted number of elements (using limitTo) and then load more as the user scrolls for instance. Many directives address this concern (look for "infinite scrolling")
All in all, I think it is still worth trying to optimize an Angular application rather tham switching to native JS, most of the time the lag comes from a developper mistake: some applications have thousands of watchers and run pretty smoothly (*cough* like mine *cough*).