Ember is very slow at rendering lists

@gunn I’ve updated the link in that response. It must have gotten lost in the shuffle.

Here is one particular performance discussion that I know of: https://github.com/emberjs/ember.js/pull/2455

GitHub issues is a generally a good spot to look if you want to lend a hand! https://github.com/emberjs/ember.js/issues?direction=desc&labels=performance&milestone=&page=1&sort=updated&state=open There is a flag for performance items.

I can’t speak to the benchmarks being tracked in any way.

@ebryn if you take a look at my second post in this thread, I was making comparisons on multiple fronts:

Learning Curve - Angular

Performance / Scalability - Ember

Mindshare - Angular Documentation - Tie

Testing - Angular

There’s actually a few more specific facets that are in ember’s favor (routing, advanced templating, etc.), but it has to have some wins at the macro level to be adopted by our org. Believe me, I see the potential in Ember, and I want to stick with it. But why am I working with non-native objects and writing obj.get(‘magicstring’) if performance with rendering and databinding isn’t better when dealing with big data?

@tjohn and I ran into this ourselves and took some comprehensive benchmarks. We believe that part of the problem stems from the fact that the Ember render buffer is very memory intensive. We proposed switching the render buffer from string concatenation to a document fragment.

Thoughts?

@wycats already has htmlbars in progress

I am super excited about htmlbars shipping with ember

https://github.com/wycats/handlebars.js

That said, if you are doing tons of binding that often becomes a bottleneck, I have not noticed any inherent perf issues with the render buffer. Most of the pain has been around excessive bindings and excessive view creation.

https://github.com/tildeio/htmlbars

list-view isn’t the best fit for all things.

It works, but is more akin to what you would expect from native frameworks, then the web, so it is not a drop in for general solutions.

The future of list-view is likely going to stay along the same lines, and potential improvements would be:

  • variable width/height.
  • less caveats.

As for naive rendering of large lists, we have some good headroom for improvement and the more we can improve the base line the more milage we can get. But even with this, there will be limitations.

For those interested, some related experimental lazy block rendering work is being done in blink:

2 Likes

I’ve asked @wycats about list rendering performance. The suggestion was to user either the Group Helper or Ember.ListView , however both have their own caveats yet. The former discards bindings per element and registers binding for the whole collection, meaning if something is changed in the collection, it will be re-rendered as a whole. The latter works with fixed height.

The group helper works in a few different ways.

It can “group” together several properties to reduce the amount of virtual views created. For example:

{{#group}}{{firstName}} {{middleName}} {{lastName}}{{/group}}

This would create only one virtual view for the whole group block instead of three (one for each property).

The big performance savings come when you use it in combination with each:

{{#group}}
  {{#each people}}
    {{firstName}} {{middleName}} {{lastName}}
  {{/each}}
{{/group}}

This creates a single virtual view encompassing the contents of the group. If any property changes, the whole group gets rerendered though. This is good for inner loops whose data changes infrequently and would be inexpensive to rerender. A list of tags comes to mind.

For larger lists, you’ll want to use the groupedRows option as well:

{{#group}}
  {{#each people groupedRows=true}}
    {{firstName}} {{middleName}} {{lastName}}
  {{/each}}
{{/group}}

This works almost like:

{{#each people}}
  {{#group}} 
    {{firstName}} {{middleName}} {{lastName}}
  {{/group}}
{{/each}}

Except nesting group inside of each will add an extra unneeded virtual view per row compared to nesting each inside of group and using groupedRows=true.

More details are here: https://github.com/emberjs/group-helper

Hope that helps! Anyone in need of performance help please feel free to get in touch with me.

7 Likes

Ember beats every other framework in rendering big lists. Check out this statistics of insanely big tables

by the way! Here is the lib to render big lists faster GitHub - eviltrout/ember-cloaking: Support for not rendering offscreen views in an Ember app for performance I bit surprised this link isn’t in this topic yet.

Having built a massive app or two in the past (one of them for the Australian Mining Industry collecting sensor reading and fuel transaction data): I have to say that most of poeples’ imagined ideas of performance are usually just plain wrong: You should optimize based on reality, not some constructed idea of reality.

Interestingly, the TodoMVC app is based on building a TODO app. If you asked @tomdale to build an App which is performant on massive lists, I’m pretty sure you’d get a different thing out of him. Sidenote: Personally I’ve never had a TODO list with 2000 items in one list! God forbit I ever do.

If your app has 2000 item lists in it, on the one page, you have a serious UX problem!

“Languages, libraries and frameworks don’t scale. Architectures do” and Ember promotes an amazingly scalable architecture. You can adjust it to fit your needs like a comfortable glove.

I really think we could do with improving the ramp to learning to make it ridiculously easy and that’d give us some amazingly good PR. Perhaps at version 2? :smile: I was talking about this at Documentation & Testing - #5 by JulianLeviston a day or so ago. Education / documentation improvement would also then mean people would reach for the right thing at the right time, IMHO, because they’d understand when to use what.

Aw man! That’s so cool. Why isn’t it in Ember proper? :smile:

It’s actually the standard way built in iOS text scrollers work as you probably already knew :wink:

If your users are used to; and sometimes even prefer working in spreadsheet applications you can argue that 2000 item lists is bad UX all day long; but it’s still what the users demand.

You can’t call Ember a framework for ambitious web applications and then essentially say “Your list is too ambitious”

But I do agree in general; you’re better off if you can design to prevent having to display large lists.

I agree. I think performance baseline is very very very important, especially for startups like us:

  • The market is competitive. It has been shown in companies that I have worked for that performance drives engagement. 100ms does matter.

  • When the team scales, not everyone would understand how to write optimized code. The baseline needs to be good enough such that even an inexperienced developer could write reasonably fast code.

Also I do not think todo list is a good benchmark.

In a normal list view, you would usually have 5+ bound attributes and 3+ actions in each row. I think we should simulate that to get a real sense of performance in real applications and optimize for that.

I don’t think he was necessarily saying it’s bad UX, but it is a valid UX concern for any particular application. And definitely a concern that might affect your choice of framework, based on baseline performance of large lists.

But – if 2000+ item lists is your use case, I think we can all agree there’ll be optimizations to be made in any framework that will take an application from usable to fast.

  • how about 2000+ comments? Imagine wikipedia rewritten with ember.js those guys have billions of comment under popular controversial articles

Wikipedia don’t have 2000+ comments on the screen at once. They use pagination IIRC. We’re agreeing here.

Optimizations are specific to use cases. Hopefully that’s evident. Consider the gaming industry and its need for graphics cards, for a great example.

The takeout from this is just as @matthooks says: any application which has a lot of “data” will need to do at least some optimization for their particular case, and it’ll probably be bespoke and involve extension to the default architecture.

The great news is this extension capability is baked right into Ember, and it’s just as easy as doing most other things in Ember. Ember’s main focus out of the box is being able to update things on the screen superfast and efficiently, and provide a flexible way to change that default focus if that’s not your primary aim.

Totally agree. I just wanted to point out that 2000+ it’s not an UX fail (pagination is kind of fail at least versus endless scrolling).

Worth to mention that only initial render is slow while updating particular item is superfast! Faster than any other framework out there.

In an interesting twist: at the March 6 (2014) Ember Meetup, part of the conversation revolved around how poorly ember is suited to render long lists of data. “Long” seems to be somewhat subjective, but the number was very low - as in 50 or so.

An example strategy would be this (let’s just assume an over-use of jQuery, for the moment):

  1. Make a $.getJSON() call to receive your list data. Each data list item would include the JSON to represent the item “in full”
  2. Loop over the data outside of Ember - in our jQuery over-use case, consider a $.each(data, function(index,value){}) type of treatment. Use jQuery and your favorite jquery-handlebars integration technique to render the content
  3. Use additional jQuery to assign actions and engagements
  4. When an individual item is acted upon - going to an “edit” modal, for example, bootstrap the item data into the store (remember, the initial JSON packet had the “full” data structure for each item)
  5. When the item activity is complete, use your best judgement to keeping the item in the store or removing it.

**Again, this is just a conversational strategy and may not work for your project! Consider this statement before you burn me at the stake :smile:. **

I am still giving this some consideration. On the one hand, you are building an Ember App and will probably err toward Ember and “the Ember Way”. On the other hand, UX and presentation are key for User Buy-in and perhaps being a little more judicious about our model usage is “okay”.

Regardless of strategy, this Meetup conversation has made me start asking, very often, “When do I need a Model, really?”.