Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Jul 2014
    Posts
    1
    Vote Rating
    0
    derek-meulmeester is on a distinguished road

      0  

    Default Provide silent flag for commitChanges and rejectChanges on Ext.data.Store

    Provide silent flag for commitChanges and rejectChanges on Ext.data.Store


    Ext version tested:
    • Ext 4.2.1
    Browser versions tested against:
    • Chrome Version 36.0.1985.125 m
    DOCTYPE tested against:
    • html
    Description:
    • I developed a window which contains a grid for displaying simple data (~5 attributes, max 1000 records).
      The grid has a check column so after I load the array into my store I invoke the commitChanges method so that I can detect when one of the records is modified:
      Code:
      ...
      store.loadData(data);
      store.commitChanges();
      ...
      For small amounts of data (less than 50 records) this is fine. But more than that and I noticed big performance issues, and actually crashed Chrome trying to load 1000 records.

      I started looking into it and realized that the issue was in the commitChanges invoking commit on each store record but not being able to do so with the silent flag.
    Steps to reproduce the problem:
    • Create an Ext.data.Store
    • Create a Grid which references that store
    • Create a Window which contains the grid
    • Load the store using Ext.data.Store.loadData(array) with an array containing 100 records
    • Commit the changes using Ext.data.Store.commitChanges
    The result that was expected:
    • Did not expect it to take so long. Also don't expect it to crash the browser on array sizes of ~1000
    I'm proposing adding the silent flag to the commitChanges and rejectChanges methods of the Ext.data.Store as shown here:
    Code:
    commitChanges : function(silent){    
        var me = this,
            recs = me.getModifiedRecords(),
            len = recs.length,
            removed = me.removed,
            i = 0;
        
        for (; i < len; i++){
            recs[i].commit(silent);
        }
        
        // Since removals are cached in a simple array we can simply reset it here.
        // Adds and updates are managed in the data MixedCollection and should already be current.
        if (removed) {
            removed.length = 0;
        }
    },
    rejectChanges : function(silent) {
        var me = this,
            recs = me.getRejectRecords(),
            len = recs.length,
            i = 0,
            rec;
        
        for (; i < len; i++) {
            rec = recs[i];
            rec.reject();
            if (rec.phantom) {
                me.remove(rec);
            }
        }
        
        // Restore removed records back to their original positions
        recs = me.removed;
        if (recs) {
            len = recs.length;
            for (i = len-1; i >= 0; i--) {
                rec = recs[i];
                me.insert(rec.removedFrom || 0, rec);
                rec.reject(silent);
            }
            
            // Since removals are cached in a simple array we can simply reset it here.
            // Adds and updates are managed in the data MixedCollection and should already be current.
            recs.length = 0;
        }
    }
    I put together a sample test application in Sencha Fiddle.
    https://fiddle.sencha.com/#fiddle/82i
    Here is the code used to test:
    Code:
    ////////////////////////////////////////////////////////////////
    //
    //                     RESULTS Ext JS 4.2.1
    //
    // I ran this code setting the `len` variable equal to each
    // of the first NUM RECORDS columns with `silent` set to
    // TRUE and FALSE and recorded the average time on a few
    // executions. Adding silent to the commitChanges and
    // rejectChanges becomes significant when loading data into
    // a grid.
    //
    //--------------------------------------------------------------
    // NUM RECORDS  |    WITHOUT SILENT(ms)   |    WITH SILENT(ms)
    //--------------------------------------------------------------
    // 1                  35                        30
    // 10                 150                       20
    // 50                 776                       30
    // 100                1800                      50
    // 200                5500                      85
    // 500                21317                     150
    // 1000               CRASHED Chrome            300
    //                    Version 36.0.1985.125 m    
    // 2000                                         550
    // 5000                                         1400
    ////////////////////////////////////////////////////////////////
    Ext.application({
        name : 'DS',
    
    
        launch : function() {
            var i = 0,
                len = 1000,
                silent = true,
                start = 0,
                testData = [],
                testObj = {
                    'nickName'  : 'Bob',
                    'firstName' : 'Bob',
                    'lastName'  : 'Bobberson',
                    'age'       : 78,
                    'address1'  : '123 road',
                    'address2'  : 'apt 123',
                    'city'      : 'city',
                    'state'     : 'state',
                    'country'   : 'country'
                },
                store = Ext.create('Ext.data.Store', {
                    storeId    : 'myStore',
                    data    : [],
                    fields    : ['nickName', 'firstName', 'lastName', 'age', 'address1', 'address2', 'city', 'state', 'country'],
                    commitChanges : function(silent){
                        var me = this,
                            recs = me.getModifiedRecords(),
                            len = recs.length,
                            removed = me.removed,
                            i = 0;
                        
                        for (; i < len; i++){
                            recs[i].commit(silent);
                        }
                        
                        // Since removals are cached in a simple array we can simply reset it here.
                        // Adds and updates are managed in the data MixedCollection and should already be current.
                        if (removed) {
                            removed.length = 0;
                        }
                    },
                    rejectChanges : function(silent) {
                        var me = this,
                            recs = me.getRejectRecords(),
                            len = recs.length,
                            i = 0,
                            rec;
                        
                        for (; i < len; i++) {
                            rec = recs[i];
                            rec.reject();
                            if (rec.phantom) {
                                me.remove(rec);
                            }
                        }
                        
                        // Restore removed records back to their original positions
                        recs = me.removed;
                        if (recs) {
                            len = recs.length;
                            for (i = len-1; i >= 0; i--) {
                                rec = recs[i];
                                me.insert(rec.removedFrom || 0, rec);
                                rec.reject(silent);
                            }
                            
                            // Since removals are cached in a simple array we can simply reset it here.
                            // Adds and updates are managed in the data MixedCollection and should already be current.
                            recs.length = 0;
                        }
                    }
                }),
                win = Ext.create('Ext.window.Window', {
                    title   : 'INFO GRID',
                    height  : 300,
                    width   : 280,
                    layout    : 'fit',
                    items    : {
                        xtype    : 'grid',
                        columns: [{
                            header      : 'First Name',
                            dataIndex   : 'firstName'
                        }, {
                            header      : 'Last Name',
                            dataIndex   : 'lastName'
                        }, {
                            header      : 'Age',
                            dataIndex   : 'age'
                        }],
                        store: Ext.getStore('myStore')
                    }
                }).show();
            
            for (; i < len; i += 1) {
                testData.push(Ext.clone(testObj));
            }
            
            start = new Date().getTime();
            store.loadData(testData);
            store.commitChanges(silent);
            
            Ext.MessageBox.alert('Results', 'Loaded ' + store.getCount() + ' records in ' + (new Date().getTime() - start) + 'ms');
        }
    });

  2. #2
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    17,148
    Vote Rating
    673
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    If you're doing bulk events on the store, you should do:

    Code:
    store.suspendEvents();
    // Do stuff
    store.resumeEvents();
    theView.refresh();
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

Thread Participants: 1

Tags for this Thread