backbone-nested icon indicating copy to clipboard operation
backbone-nested copied to clipboard

Improve set performance (IE8)

Open Taffa opened this issue 13 years ago • 4 comments

It seems that set is very slow operation in IE8 this leads to poor performance for example if you need to iterate over collection of models and set bunch of attributes. Consider ways to improve it's performance.

Taffa avatar Aug 29 '12 16:08 Taffa

Can you provide some example code? Are you noticing that IE8 performance is particularly bad, or is that just what you're using? Backbone.Model's set() operation is the upper bound for this plugin - it adds functionality to each operation, so it will always be [at least marginally] slower. Speed tests were just added to the test suite, so please include relative benchmarks if you can.

afeld avatar Aug 29 '12 17:08 afeld

I can speak only about my own app perormance, which is not good in any machine with IE8 I can provide code example and stacktrace later. Here are speed test results for IE8 and for comparsion Firefox14

http://tinyurl.com/ce9xaok and http://tinyurl.com/cspfcxt

Taffa avatar Aug 29 '12 20:08 Taffa

Some suggestions / ideas: Is this possible to work around by setting your attributes all at once (with a hash) instead of iterating and calling set for each of them, and if not is it still slow if you set them with the option { silent: true }?

isakb avatar Aug 29 '12 22:08 isakb

If I am reading this right, overall re-bind performance can be dramatically improved by changed the following lines

      if (attrPath){
        opts = opts || {};
        this._setAttr(newAttrs, attrPath, value, opts);
        // performance fix - this is a basic set on the root object, no need to trigger change events for the entire model
        newAttrs = {};
        newAttrs[attrPath] = value;
        // done performance fix
      } else { // it's an Object

Prior to this change lets say you had an object like:

    return Backbone.NestedModel.extend({
        defaults: {
            artists: [],
            selected: null,
            loading: false
        },
        initialize: function() {
            var self = this;
            User.getFavoriteArtists('xdigitalegox').done(function(results) {
                     self.set('artists', results);
            });
        },
        focus: function(artist) {
             this.set('selected', artist);
        }

Anytime I called myObject.focus(...) I was getting what I expect a change:selected event and a more general change event.

However, I was also getting a change:artists event!

This caused my HTML binding (rivetsjs) to repeat needlessly and the DOM to be manipulated for an entire list of artists (redrawing 50+ html elements).

I only noticed this on slower browsers and devices (as my tablet had such a horrendous slowdown) it took awhile to track this down, but with the above change it dramatically speed up performance as now I only get change events for the targeted object. Haven't run through all tests but this seemed to help alot.

Capture

terrancesnyder avatar Jan 05 '13 21:01 terrancesnyder