Optimizing large tables


#1

I was just wondering if there was some list of best practices available for optimizing the rendering of large tables and/or lists.

In my application I noticed that the data is received quickly enough after the request, but that the page takes much time to appear while it is running through the {{#each}} loop.


#2

Often, the issue is related to DOM rendering, not Ember-specific code.

You might consider the following libraries, which can help in specific situations:


#3

Thanks for the tips. Currently I already have my own component defined which uses a computed property in the model:

var Meeting = DS.Model.extend({
    city: DS.attr('string'),
    weekday: DS.attr('string'),
    start: DS.attr('string'),
    finish: DS.attr('string'),
    address: DS.attr('string'),
   
    record: function() {
        var html = '';
        html += '<td>' + this.get('city') + '</td>';
        html += '<td>' + this.get('weekday') + '</td>';
        html += '<td><span class="whitespace-nowrap">' + this.get('start') + '-' + this.get('finish') + '</span></td>';
        html += '<td>' + this.get('address') + '</td>';
        return new Ember.Handlebars.SafeString(html);
    }.property('city', 'weekday', 'start', 'finish', 'address')
});

In my template:

<tbody class="hover-cursor">
    {{#each meeting in listMeetings}}
        {{#link-to 'meetings.show' meeting tagName="tr" }}
            {{meeting.record}}
        {{/link-to}}
    {{/each}}
</tbody>

This seems to help a little bit but not alot, and besides it’s a very awkward and inelegant solution which is not very maintainable.


#4

I’m not sure I understand why you’re parsing HTML in the model. Wouldn’t it be simpler do something like:

var Meeting = DS.Model.extend({
    city: DS.attr('string'),
    weekday: DS.attr('string'),
    start: DS.attr('string'),
    finish: DS.attr('string'),
    address: DS.attr('string')
});

Template:

<tbody class="hover-cursor">
    {{#each meeting in listMeetings}}
        {{#link-to 'meetings.show' meeting tagName="tr" }}
           <td>{{meeting.city}}</td>
           <td>{{meeting.weekday}}</td>
           <td><span class="whitespace-nowrap">{{meeting.start}} - {{meeting.finish}}</td>
           <td>{{meeting.address}}</td>
        {{/link-to}}
    {{/each}}
</tbody>

This would be easier to maintain, and might benefit from any optimizations made by HTMLBars. (I’m not sure how Handlebars handles SafeString html updates.)


#5

Yes you’re right. That’s exactly what I was originally doing, but resorted to the other model solution when the template solution turned out to be way too slow. Thought that I was being clever to render and cache the table rows like this, but perhaps there is a better way.


#6

Check out ember cloaking. If you are willing to wait a few days, check out smoke-and-mirrors.

I maintain the es6-flattened branch on cloaking which you can use with ember-cli: https://github.com/eviltrout/ember-cloaking

I’m getting close to a 0.1.0 release (although some of this is already in heavy use in a mobile app) on https://github.com/runspired/smoke-and-mirrors

You can see a demo of what it can do for a table here: http://runspired.github.io/smoke-and-mirrors/

A better demo of which which includes an example using the occlusion-culling component is coming out within the hour.


#7

Here’s that demo: http://runspired.github.io/smoke-and-mirrors/#/dbmon-occlusion-collection

This is Ember 1.11 This is NOT Glimmer.


#8

Collection view instead of the #each helper. You’ll see gains. Also, run your app in production mode since mandatory setter (dev-only feature) gives a nice perf hit.