Home Strategies for Angular Performance in Large Table?
Reply: 1

Strategies for Angular Performance in Large Table?

uglycoyote Published in 2017-11-14 16:13:01Z

I'm working on a project that's using AngularJS v1.5.11 to display a large table of data -- it is a continuous build system which displays a table of rows for each change that comes in to source control. The columns are some data that's "static" like the information about the change, and some dynamic columns which show the current state of various automated builders/testers for that change. The page polls several different REST endpoints from a build server, and updates the page with current results from many different build machines.

I have made quite a few improvements to the page to add additional information, now I'm running in to performance issues due to too many watchers. Full-page digests happen frequently and the number of watchers is in the thousands, causing some interactive operations to have several seconds of delay.

I use the :: ("one-time-binding") syntax already where applicable, but the heaviest use of watchers is in the columns which show the build/test results and those need to update as new data comes in. One-time-binding doesn't make sense in those cases.

I have already come up with a solution which involves disabling the watchers on old rows, since after a certain point we can guess that a particular row is not going to go get updated anymore (once all of the builders have moved on to processing a more recent change). I'm using something similar to this page, having a suspendable directive which can remove the watchers from a row upon an event.

There are a couple problems I'm having with the approach of suspending watchers

  1. Sometimes those old rows do get new data contrary to our heuristic which deactivates the row, e.g. someone goes back and manually re-runs a build on an old change. Then that row fails to display the up-to-date data
  2. There are some interactive "ng-click" features that fail to work on rows that have been deactivated.

The other issue that I have is that currently the table is restricted to a limited number of rows, but I would like for it to automatically add rows when the user scrolls down ("infinite scrolling") so that they can view old data. This is going to dramatically increase the number of rows and thereby increase my performance issues with watchers.

My Questions:

  1. Are there any other performance strategies that would help other than what I'm doing (one-time-binding and disabling watchers)?

  2. How do others approach problems like this in Angular, or is Angular just not really well suited to this kind of a high-density information display? (A previous implementation of a similar page using jQuery runs much faster because once it adds a row, it pretty much leaves it alone, it just sits there in the DOM not incurring any extra cost each time new data comes in)

  3. I realize I'm on an old version of Angular, and that Angular2 is supposed to be better for performance. What are the specific features in newer versions that might help with these issues?

Chris Reply to 2017-11-17 09:29:54Z

It's hard to give directed answers without code or examples but here's some suggestions that may help you out

  1. Run NgStats and look at your watcher count and how fast your digest loops take. This will help focus your efforts.
  2. One time binding is a good idea. If you are still seeing performance problems with this I'd look at your ng-repeat code.
  3. Improve ng-repeat by using track by
  4. Ensure you never bind to a function i.e. ng-repeat="$ctrl.mySortedData()" or <div>{{$ctrl.getTitle()}}</div> as it makes digest cycles slower.
  5. Anecdotally some developers see ng-bind perform better than handle bars
  6. If you are not already, move to one way binding with Angular components, it'll help
  7. It's a bit of a brute force method but I find it helps sometimes: Comment out sections of your page to see what specific sections cause the most slow down (refer to #1). Once you have identified these regions you can focus your time there.
  8. Reducing the number of watchers is key to performance. It can be as simple as using a ng-switch rather than 3 ng-ifs.
  9. Not Angular related, but Tables themselves are slow to render by the browser, if possible consider moving to a div + css styled display.

Personally I am able to render thousands of on screen elements without any noticeable drop in performance using the methods above. I have never had to suspend watchers and sounds like something that is difficult to maintain. I personally wouldn't recommend that.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.320744 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO