1. #1
    Sencha - Ext JS Dev Team dongryphon's Avatar
    Join Date
    Jul 2009
    Posts
    1,346
    Vote Rating
    134
    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 Ext JS 4.1 - Layout and Rendering Performance

    Ext JS 4.1 - Layout and Rendering Performance


    In the past few weeks, we have been evaluating some exciting opportunities to improve performance in Ext JS 4.1. While these optimizations build upon the foundation laid by Ext JS 4.0, they may potentially impact existing code in a couple narrow use cases. So before getting too far down the path, we want to first discuss these ideas and solicit feedback from the community.

    Recap
    Improving performance was one of the major design goals for Ext JS 4.0. Given that the single, most dominant factor in overall performance was layout performance, it is not surprising that layout optimization was a large part of the Ext JS 4.0 release. Performance, however, was not the only goal. Increased flexibility was another major design goal for Ext JS 4.0. To provide this flexibility, many aspects of the user interface were refactored into Components, Containers and Layouts, whereas previously these were often hard-coded aspects of a Component (e.g., tools in a panel header).

    When compared one-to-one, the individual layout managers in Ext JS 4.0 handily out perform their counterparts in prior versions. In previous versions, layout managers interrogated, moved and resized DOM elements sequentially. In Ext JS 4.0, on the other hand, the layout managers read the DOM, make calculations and then move/size elements all in separate phases (in parallel). This avoids expensive read/write interleaving and radically improves performance. The layout managers in Ext JS 4.0 also do a much better job of handling auto-sized components such as flowing text or images, or containers of such things.

    Unfortunately, all this flexibility has a cost and the sum of these costs can add up quickly. While deeply nested component trees are one, rather obvious, way to see the total cost increase, sometimes cost can come from unexpected places like the combination of configuration options. The perceived impact of all this depends, of course, on the browser. Browsers such as Chrome (WebKit, Safari), Firefox and Opera tend to handle the increased load well. The same cannot be said for IE, especially the older versions like IE8, IE7 and our most beloved IE6.

    All this has been widely observed as the community has dug into Ext JS 4.0 and started using it in real-world applications. It is fair to say that the most common issue raised by the community has been poor overall performance and, in particular, poor performance on IE.

    Phase 1
    It will come as no shock that the dominant element in overall performance remains layout performance. The other contributors are less obvious. Using the Themes example, the breakdown is roughly this for IE8:
    • layout: 68% (58% + getStyle:10%)
    • render: 23% (14% + renderSelectors:9%)
    • misc: 9%
    Render Selectors
    Our first phase of optimization was delivered in Ext JS 4.0.5 where we addressed the contribution of renderSelectors. Even though they were a small part of the overall performance picture, radically improving them was relatively straightforward. In Ext JS 4.0, after elements are rendered to the DOM, renderSelectors are used to find important child elements and store references to them on the component for later use. For example, the renderSelectors for a Button prior to Ext JS 4.0.5 looked like this:

    Code:
        {
            btnEl  : this.href ? 'a' : 'button',
            btnWrap: 'em',
            btnInnerEl: '.x-inner',
            btnIconEl: '.x-icon',
            arrowEl: '.x-arrow'
        }
    After applying the renderSelectors, the Button component gained a "btnEl" property that referenced the button or anchor Element. This mechanism, while elegant and flexible, did not perform very well on IE as can be seen by its prominent presence in the breakdown above. The solution was to add a new mechanism based on id's. So, in Ext JS 4.0.5, the button element is now found by the id "compId-btnEl" where "compId" is the id of the component.

    When we applied this to most uses of renderSelectors throughout the framework, it resulted in an 8x improvement in IE8 and, surprisingly, a 25x improvement in Firefox! This effectively pushed renderSelectors off the performance hit list: what was previously 9% of overall performance has effectively disappeared from view.

    While the net gain to overall performance was not all that noticeable, this also had the positive side-effect of making id's more readable and useful to tools like Selenium. Unfortunately it had the downside of breaking code that customized renderTpl's. While the fix was simple: add the necessary id attributes to the custom renderTpl; we want to apologize to those adversely effected for not providing an appropriate advisory regarding this change.

    Phase 2
    The larger optimizations to layout and rendering (discussed below) require internal changes across the framework. As such, the Themes example, which contains one of just about every component and layout, is an unsuitable benchmark at this early stage. As a proof-of-concept, we have devised a simpler, yet we believe representative, test case that required us to change far fewer components and layouts.

    The initial test case is a Viewport with a vbox layout of 10 panels each with an hbox layout and 5 child panels. This makes for a total of 60 panels, 50 of which with titles. These 50 panels each use dock layout to dock their headers and those headers use an hbox to contain the text component with the panel's title. The text component's width is flex:1 and its height is auto. The baseline performance for this test, prior to any further optimizations, was the following:
    • layout: 1770ms
    • getStyle: 255ms (5461 calls)
    • render: 400ms (varies widely from run-to-run and ranges between 350ms and 700+ms)
    • Total time: 2630ms
    (All measurements were made using IE8 on a Windows 7 laptop with Core i3 @ 2.1GHz)

    Layouts
    One of the big costs in a layout is the proper handling of auto-size components: width, height or both. In Ext JS 4.0, this often requires a layout to invoke its child layouts multiple times to achieve the correct result. For example, the title in a Panel has an auto height but that is dependent on the element having the proper width as calculated by the layout of its owner (the header) which in turn depends on the width of its owner (the panel). The panel, however, needs the height of the header in order to dock toolbars and the like, but the height of the header depends on the height of the text component it contains.

    To further complicate matters, in Ext JS 4.0, changes to a component now automatically trigger the necessary layouts, thereby freeing the developer from having to know which component(s) need to have their layout recalculated. This means that layouts have to be able to run from the bottom-up (e.g., to handle setTitle on a Panel). Layouts in Ext JS 3.x and before were much simpler and were only ever executed top-down. All this complexity was at the root of many of the bugs fixed in Ext JS 4.0.x. This was often both a correctness issue (layouts not being recalculated when needed) and a performance issue (layouts being redundantly recalculated).

    Merely making the layouts correct and predictable is not enough. To take the layout optimizations made in Ext JS 4.0 to the next level, we need to minimize read/write interleaving globally not just locally, that is, for the whole component tree rather than for each component. To do this we need a "layout solver": a class that can see the whole problem, organize the various layout managers, track their dependencies, cache their DOM reads, buffer any calculated results and coordinate writing updates to the DOM.

    This would also definitively solve one of the biggest complexities in the Ext JS 4 layout system: ensuring that all necessary layouts are recalculated while simultaneously avoiding redundant calculations.

    The initial results here are very promising: a 5x layout speed improvement! That is significant enough to drop layout time below the render time! We also see a significant reduction in the number of DOM reads (getStyle calls).
    • layout: 290ms
    • getStyle: 185ms (3544 calls, down by 1917)
    • render: 550ms* (see above)
    • Total time: 1370ms (a 2x overall improvement)
    Rendering
    With layouts no longer the primary bottleneck in the initial presentation of a page, our attention turned to the new top culprit: rendering. Ext JS 3.x and 4.0 take a hybrid approach to creating DOM elements. The primary element for a component, as well as other elements, are ultimately created using the createElement DOM API. In Ext JS 4.0, the internal structure of a component is produced using the XTemplate class and an internal property called the "renderTpl". This part of the rendering eventually results in setting innerHTML to a block of generated markup.

    Generally speaking, innerHTML is a significantly faster approach for generating large trees of elements, especially on IE. This was less of a problem in Ext JS 3.x because many parts of the UI were just markup and not first-class components. This meant much more of the DOM was created via innerHTML. In Ext JS 4.0, now that almost everything you can see is a component, this balance has greatly shifted towards the use of createElement.

    The strategy for optimal rendering performance then is to render the entire component tree into markup in one pass and insert that into the DOM with one write to innerHTML.

    In our initial tests, this approach further reduces total time by 20%-30%:
    • layout: 230ms
    • getStyle: 100ms (3222 calls, down by another 322)
    • render: 180ms (varies between 150ms and 300ms)
    • Total time: 950ms (a 2.5x to 3x overall improvement)
    Discussion
    After all that back-story, even the most patient reader is probably thinking:

    This all sounds wonderful... and we are all certainly glad that the development team hasn't been ignoring our cries, but what does it mean to me and my code? Beyond the whole 'faster is better' thing...

    We are looking at two important areas where these changes will impact existing code...

    Impact on Custom Layouts
    Significant refactoring will be necessary for a layout class to participate in the new scheme. We don't imagine that too many folks in the community are writing custom layouts, but those that have will have some work to do. The amount of refactoring necessary will depend on how closely the layout follows the read/calculate/write division used throughout Ext JS 4.

    For example, the box layout (the base for hbox and vbox) required several "spot" changes, but remained structurally very much the same. The same was true of the dock layout. These layouts are two of the most complex layouts, so we are optimistic that the changes will not be overly drastic in most cases.

    Impact on Custom Components
    More importantly is how bulk rendering will effect custom components and at the center of this is the onRender method. Currently, onRender is overridden for two very different purposes:
    1. To do work that requires the component's elements to exist (like adding listeners), after first calling the base class.
    2. To make last minute modifications that effect the rendering, before calling the base class.
    The first use case is unaffected by this refactor, though overriding initEvents (now supported by all components) may often be a better choice. The second use case, however, will not work with bulk rendering. Instead, such code will need to move to the new beforeRender method.

    Lastly
    Detailed information will follow at a later date. We are only now in the early stages of this effort. Rather than wait for all the details to be sorted out, implemented and documented, we wanted to get feedback on the general approach.

    What are your concerns, questions, suggestions?
    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!"

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

      0  

    Default


    Excellent summary Don.

    And one side effect of this change is that within any onRender call, and any render event handler, the entire Component tree will have been rendered into the DOM.

    There is no longer a need to hook into the first ocurrence of the afterlayout event which was what you always had to do to inject functionality which had to access child Components, and was always slightly uncomfortable.

    So now you can place an onRender override into your topmost application Container, and, using ComponentQuery gather descendant Component references and references to any descendant's DOM structure. The DOM structure will all exist at that time. It won't have been layed out to its final "shape", but it will be there.

  3. #3
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,360
    Vote Rating
    81
    jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all

      0  

    Default


    I read through this and am extremely excited. As I've toured many countries & visited many companies since Ext JS 4.0's launch, the performance concerns were equally echoed.

    That said, I'm very glad you guys are working so hard to fix this. The general consensus is that Ext JS 4.0.x is not ready for production apps, thus a lot of folks just now jumping onto the Ext JS bandwagon are starting off with 3.x, despite my objections.

    4.1 is expected to be a huge improvement over 4.0 and we're all excited about it and eagerly anticipating it.

    Is there any way that you guys can publicly produce benchmark pages that can allow people to see the performance increase themselves?

    Also, are you making sure that you test each layout and at least 5+ nested layouts deep with varying layout managers?

    The extending of onRender to hook Managed Events ("mon") is not truly necessary. I learned that you could specify an element directly as a listeners object to hook events.

    Code:
    Ext.create('Ext.window.Window',{
        width   : 200,
        height  : 100,
        html    : 'Click the window body!',
        listeners : {
            body : {
                click : function() {
                    var id  = this.dom.parentNode.id,
                        win = Ext.getCmp(id);  // yeah, cheating, I know! But, it's not static!
                    win.el.mask('Boo!')
                }
            }    
        }
    }).show();
    With this technique, culturally, I don't see the need to extend onRender for that purpose. That is, unless you need to hook event handlers on deeply nested elements, I suppose.

  4. #4
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,073
    Vote Rating
    854
    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 jgarcia@tdg-i.com View Post
    Is there any way that you guys can publicly produce benchmark pages that can allow people to see the performance increase themselves?

    Also, are you making sure that you test each layout and at least 5+ nested layouts deep with varying layout managers?
    Not saying anything official (as I have no powers!) but if the core dev team is too busy keeping on the performance kick ass bandwagon, then I will. To turn the public view on performance with 4.0, we need concrete evidence to back up our claims and not just numbers but (and as you suggest) public pages that people can go to themselves. Don has provided a pretty decently sized use case with the 60 panels and with numbers but it should be tested on more than one test.

    Also, this post could be turned into a blog as it's well written too
    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.

  5. #5
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,360
    Vote Rating
    81
    jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all

      0  

    Default


    I'd like to keep track of changes to the component lifecycle, should i checkout the 4.1.x or 4.1.0 branch?

  6. #6
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,073
    Vote Rating
    854
    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 jgarcia@tdg-i.com View Post
    I'd like to keep track of changes to the component lifecycle, should i checkout the 4.1.x or 4.1.0 branch?
    4.1.0 is bleeding edge. That's where we would push too
    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.

  7. #7
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,360
    Vote Rating
    81
    jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all

      0  

    Default


    Had to push back to 4.0.6. Building 4.1 is completely broken.

    See: https://gist.github.com/1127847

  8. #8
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,073
    Vote Rating
    854
    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 jgarcia@tdg-i.com View Post
    Had to push back to 4.0.6. Building 4.1 is completely broken.

    See: https://gist.github.com/1127847
    They been having problems with 4.1. I know Thomas Aylott was working on it with ST2 and it was affecting 4.1 also. Thought they had it fixed, but apparently they are still working on it.
    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. #9
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,073
    Vote Rating
    854
    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


    Jamie says the build bootstrap works in 4.1 but build all does not.
    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.

  10. #10
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,360
    Vote Rating
    81
    jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all

      0  

    Default


    awesome. I will look to use that. thanks.