Angular JS ng-repeat consumes more browser memory
Asked Answered
P

3

8

I have the following code

<table>
 <thead><td>Id</td><td>Name</td><td>Ratings</td></thead>
 <tbody>
   <tr ng-repeat="user in users">
    <td>{{user.id}}</td>
    <td>{{user.name}}</td>
    <td><div ng-repeat="item in items">{{item.rating}}</div></td>
   </tr>
 </tbody>
</table>

users is an array of user objects with only id and name. number of user objects in array - 150

items is an array of item objects with only id and rating. number of item objects in array - 150

When i render this in browser, it takes about 250MB of heap memory when i tried profiling in my chrome - v23.0.1271.95.

I am using AngularJS v1.0.3.

Is there an issue with angular or am i doing anything wrong here?

Here is the JS fiddle

http://jsfiddle.net/JSWorld/WqSGR/5/

Persnickety answered 28/12, 2012 at 5:35 Comment(0)
K
12

Well it's not the ng-repeat per se. I think it's the fact that you are adding bindings with the {{item.rating}}.

All those bindings register watches on the scope so:

  • 150 * 2 = 300(for the 2 user infos)
  • 150 * 150 = 22500(for the rating info)
  • Total of 22800 watch functions + 22800 dom elements.

That would push the memory to a conceivable value of 250MB

From Databinding in angularjs

You can't really show more than about 2000 pieces of information to a human on a single page. Anything more than that is really bad UI, and humans can't process this anyway.

Kalvn answered 28/12, 2012 at 11:19 Comment(6)
Thanks Liviu! I tried with writing a custom directive for the inner ng-repeat. That actually brought down the memory to much much lesser (around 40MB ). Here is the JS Fiddle of the same: jsfiddle.net/JSWorld/WqSGR/9Persnickety
What is the actual use case you are trying to achieve?Kalvn
For every user, i want to list the rating he has given for every item available in the descending order of rating.Persnickety
This is the correct answer. In the end if you wanted to display this much information, you'd probably be better off with a custom directive that wrote the sub-data out to the DOM rather than setting up bindings for each item.Dynamometry
I'm very interested in why that directive is crushing the memory usage so much. Why is it so much more efficient than ng-repeat? The fact is you probably shouldn't display so many items at once, but the principal remains. Why not always use such a directive? Anyone?Spinneret
@dg988 - from my understanding, there is no data binding in the directive version. It's just a direct replacement (at link time) of {{rating}} with the value of myItem.ratingEctoplasm
P
0

I want to say the leak is in the second array because you are potentially looping through the same array and displaying every item for every user row in users so depending on how large your test data is that view could get rather large. I could do a little more investigating. btw your fiddle is something entirely different.

Plowshare answered 28/12, 2012 at 6:1 Comment(1)
I have updated the fiddle. Sorry, posted the wrong link. Still the problem persists for me in my case. Why will looping cost so much memory. Is there generally an issue with using nested ng-repeats?Persnickety
I
0

Right now you are looping through 150 X 150 = 22500 items. And registering a watch (or through a directive just adding item rating) to each one.

Instead - consider adding the user's rating to the user object itself. It will increase the size of each user object but you will only loop through 150 items and register watches only on them.

Also - consider looking into Indexes. It's apparent that there could be similar users or item ratings. Just index them, so instead of looping through heavy objects, you can reduce them.

One more thing - if you are going to be running the directive the same instance, at least change the code:

var text = myTemplate.replace("{{rating}}",myItem.rating);

to a concat style string calculation:

var text = '<div>' + myItem.rating + '</div>';

This will save you a HUGE chunk on calculation. I've made a JSperf for this case, notice the difference, it's about 99% faster ;-)

Interment answered 20/8, 2013 at 19:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.