1. #11
    Sencha Premium Member skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,492
    Vote Rating
    283
    skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future

      1  

    Default Batching

    Batching


    Try to batch changes that cause re-rendering so that the rendering only happens once at the end.

    For example, changing a field value in a record will immediately update the grid. If you want to update several fields it's more efficient to batch them:

    Code:
    record.beginEdit();
    
    record.set('name', 'Tom');
    record.set('age', 17);
    record.set('member', true);
    
    record.endEdit();
    The more fields you change the more noticeable the effect will be.

    Another example is adding components to a container. The container will recalculate its layout every time add() is called. Passing multiple items to the same add() call will be much more efficient.

    Code:
    // slow
    container.add(panel);
    container.add(button);
    container.add(grid);
    
    // fast
    container.add(panel, button, grid);
    
    // using an array, also fast
    container.add([panel, button, grid]);
    In cases where no other batching mechanism exists it can help to suspend layouts temporarily:

    Code:
    container.suspendLayout = true;
    
    doSomethingThatCausesLotsOfLayoutChanges();
    
    container.suspendLayout = false;
    container.doLayout();

  2. #12
    Sencha - Ext JS Dev Team dongryphon's Avatar
    Join Date
    Jul 2009
    Posts
    1,294
    Vote Rating
    121
    dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all

      1  

    Default Re: Batching

    Re: Batching


    In 4.x, you can use the multi-value form of set which has a built-in begin/endEdit mechanism:

    PHP Code:
        record.set({
            
    name'Tom',
            
    age17,
            
    membertrue
        
    }); 
    New to 4.1, layouts are suspended via method call to avoid problems that we encountered via nested suspend/resume logic (the boolean suspendLayout is still respected). This can be done on a single component:

    PHP Code:
        container.suspendLayouts();   // plural "layouts"
        
    ...
        
    container.resumeLayouts(true);  // true=run layout if 0 suspend count 
    Or if you are manipulating multiple components, there is a global suspend mechanism:

    PHP Code:
        Ext.suspendLayouts();
        ...
        
    Ext.resumeLayouts(true); // true=run layouts if 0 suspend count 
    Don Griffin
    Ext JS Development Team Lead

    Check the docs. Learn how to (properly) report a framework issue and a Sencha Cmd issue

    "Use the source, Luke!"

  3. #13
    Sencha Premium Member skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,492
    Vote Rating
    283
    skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future

      0  

    Default deferredRender

    deferredRender


    To expand on Mitchell's earlier comment...

    When using a card layout or tab panel, be careful to consider the deferredRender option. When set to true it will cause the hidden cards/tabs to be lazily rendered. Rendering will only occur when the hidden items are first shown. When set to false, all cards/tabs will be rendered at the same time, as part of the rendering of the container.

    Usually it is better to defer rendering as it helps to break the rendering process up into smaller chunks that won't cause a noticeable delay to the user. However, rendering all the cards/tabs up front can help to improve responsiveness of the UI when the hidden cards/tabs are first shown.

  4. #14
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,496
    Vote Rating
    44
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      1  

    Default


    When using a grid, if you have a large data set, use buffered rendering.

    This means that the Store keeps a "prefetch" buffer containing a page of Records which is used when possible to load the Store.

    As long as the data set is less than maybe 100,000 rows, it's probably best to keep all the data in the client in this prefetch buffer.

    It's the rendering of a large HTML table that kills performance. That's just a fact of the HTML table algorithms. Just holding all the data should not cause problems.

    What we can do is do "just in time" rendering of the rows in the table as we scroll.

    To do this, first load the prefetch buffer with all the data. And when that is done, you can then load the Store's main data cache from the prefetch:

    Code:
    myStore = ...{
        ...,
        buffered: true,       // Tells grid to use a Paging scroll manager to scroll and refresh the table automagically
        purgePageCount: 0, // never remove pages from the prefetch buffer
        ...
    }

    Code:
    myStore.prefetch({
        start: 0,
        limit: 999999,
        callback: function() {
            myStore.load(0, 49);
        }
    });
    What that does is prefetches what is hopefully the whole data set. Then the callback loads the Store's main cache (the cache that is mapped to a <table> within the GridPanel) with the first 50 rows.

    So we only get a small 50 row table.

    As it scrolls nearly out of view, it is refreshed.

    This technique works OK in 4.0.x, but it has been really overhauled in 4.1.0 and will be extremely fast and smooth.

    The buffer-grid example in the grid directory illustrates this technique.

    Be aware that it seems that a large number of columns has an effect on the performance of HTML <table> elements too, so avoid columns which do not really need to be present.

  5. #15
    Sencha - Ext JS Dev Team dongryphon's Avatar
    Join Date
    Jul 2009
    Posts
    1,294
    Vote Rating
    121
    dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all dongryphon is a name known to all

      0  

    Default Grid store size

    Grid store size


    Obviously 100K rows may sound like a lot, but the amount of memory you can utilize in the browser is quite surprising. The ideal number may take some experimentation and will depend on the number of fields in your model as well, but you would be amazed at how much speed you can gain by using more memory.
    Don Griffin
    Ext JS Development Team Lead

    Check the docs. Learn how to (properly) report a framework issue and a Sencha Cmd issue

    "Use the source, Luke!"

  6. #16
    Sencha Premium Member
    Join Date
    Feb 2011
    Location
    Illes Balears
    Posts
    22
    Vote Rating
    0
    _matias_ is on a distinguished road

      0  

    Default


    Great thread and great tips. I think a lot of us needed this. Regarding Animal's buffered rendering suggestions, I am getting an incorrect behaviour, on both 4.0.7 and 4.1-pr1. I do not know if I am doing something wrong or if it is a bug. If someone has a clue either way, please let me know

    I am loading a buffered store in FF 7.0.1 and monitoring the XHR calls through firebug. The buffer is correctly loaded through the proxy. But when I use myStore.load(0, 49) the whole store is loaded again via the proxy and the full table is rendered, which kind of defeats the purpose.

    my test setup (I simplified it as much as I could think of)
    Code:
    Ext.define('edm.model.Doc', {    extend: 'Ext.data.Model',
        fields: [
            {name: 'id', type: 'int'}
        ],
    
    
        proxy: {
            type: 'rest',
            url: '/docs',
            reader: {
                type: 'json',
                root: "data",
                defaultRootId: 'root'
            }
        },
        constructor: function() {
            this.callParent(arguments);
        },
    });
    
    
    
    
    Ext.define('edm.store.Docs', {
        extend: 'Ext.data.Store',
        model: 'edm.model.Doc',
        buffered: true,
        purgePageCount: 0,
        clearOnPageLoad: false
    });
    
    
    myStore = Ext.create('edm.store.Docs');
    
    
    myStore.prefetch({
        start: 0,
        limit: 999999,
        callback: function() {
            console.log('prefetched')
            myStore.load(0, 49);
            console.log('loaded')
        }
    });
    the firebug output:
    Code:
    GET http:/127.0.0.1/docs?_dc=1321107103812&start=0&limit=999999
    prefetched
    GET http:/127.0.0.1/docs?_dc=1321107104216&page=1&start=0&limit=25
    loaded
    I later use the console to check the store is correctly loaded:

    Code:
    >>console.log(myStore.first().get('id'))
    1
    Update: I also tried to use myStore.load({start:0, limit: 50}); but the proxy is still accessed instead of the buffer.

    Update: I got it to work by replacing store.load by store.guaranteeRange and adding a pageSize parameter to the store:


    Code:
    Ext.define('edm.model.Doc', {    extend: 'Ext.data.Model',
        fields: [
            {name: 'id', type: 'int'}
        ],
    
    
        proxy: {
            type: 'rest',
            url: '/docs',
            reader: {
                type: 'json',
                root: "data",
                defaultRootId: 'root'
            }
        },
        constructor: function() {
            this.callParent(arguments);
        },
    });
    
    
    
    
    Ext.define('edm.store.Docs', {
        extend: 'Ext.data.Store',
        model: 'edm.model.Doc',
        pageSize: 50,
        buffered: true,
        purgePageCount: 0,
        clearOnPageLoad: false
    });
    
    
    myStore = Ext.create('edm.store.Docs');
    
    
    myStore.prefetch({
        start: 0,
        limit: 999999,
        callback: function() {
            console.log('prefetched')
            myStore.guaranteeRange(0, 49);
            console.log('loaded')
        }
    });
    the firebug output is now:
    Code:
    GET http:/127.0.0.1/docs?_dc=1321107103812&start=0&limit=999999
    prefetched
    loaded
    Last edited by _matias_; 16 Nov 2011 at 12:37 PM. Reason: Fixed

  7. #17
    Sencha Premium Member
    Join Date
    Feb 2011
    Location
    Illes Balears
    Posts
    22
    Vote Rating
    0
    _matias_ is on a distinguished road

      0  

    Default


    Did I kill the thread ?

  8. #18
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,581
    Vote Rating
    814
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Quote Originally Posted by _matias_ View Post
    Did I kill the thread ?
    No... we just staying busy
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  9. #19
    Sencha Premium Member
    Join Date
    Feb 2009
    Location
    Amsterdam, The Netherlands
    Posts
    245
    Vote Rating
    6
    Grolubao is on a distinguished road

      0  

    Default


    Consider using Base64 if there is no need to support older versions of IE:

    http://code.google.com/p/wro4j/wiki/...DataUriSupport

  10. #20
    Ext JS Premium Member
    Join Date
    Aug 2007
    Location
    Antwerp, Belgium
    Posts
    555
    Vote Rating
    27
    joeri has a spectacular aura about joeri has a spectacular aura about joeri has a spectacular aura about

      0  

    Default


    Quote Originally Posted by Grolubao View Post
    Consider using Base64 if there is no need to support older versions of IE:

    http://code.google.com/p/wro4j/wiki/...DataUriSupport
    Be aware that in IE8 data URI's are limited to 32 KB. For many purposes that is too confining.