-
30 Apr 2012 9:27 AM #1
Floating modal panels performance
Floating modal panels performance
REQUIRED INFORMATION
Ext version tested:- Sencha Touch 2.0
- iPad1 iOS 4.5.3
- iPad2 iOS 4.5.3
- In Sencha 2 popups (read modal floating panels) work slow.
- First show of almost empty popup in almost empty project takes 450-600ms. Subsequent shows take 60-150ms.
- The problem is that numbers become worse significantly with dom growth.
- In real project 1st popup show can take up to 1.3-1.5 secs and subsequent shows take 300-500ms. These are quite evident delays, annoying for a user.
- Moving popup to Viewport (btw not mentioned in specs).
- Inserting mask to dom.
- Signing to Viewport 'resize' event that results in adding Viewport size detectors to dom.
- Raising 'hiddenchange' event that results in 'painted' and 'show' events.
- 'Pained' event causes popup scroller refresh that does refresh and also calls refresh of 2 pairs of size detectors.
- Refreshes of size detectors cause 'scroll' events and as a result refresh of size detectors themselves and scroller again.
That is quite a complicated chain of events and multiple refreshes causing several dom interventions.
So, could you please revise floating modal panel show/scroll refresh/size detectors refresh strategy to see if there is anything to fix/improve?
Steps for testing:- Open the test case and type a letter in the input field.
- There is a delay before the popup is shown 1st time, keyboard hangs for some time.
- Check log:
- -> 'showBy' is slow (450-600ms)
- -> scroller doRefresh - 3 times
- -> inner size detector refresh - 3 times
- -> container size detector refresh - 3 times
- Clear input and type a letter.
- Popup is shown faster this time though not immediately.
- Check logs:
- -> 'showBy' (60-150ms)
- -> multiple scroller and detectors refreshes
- Clear and type something quickly, there are delays, ckeck logs
Code:<style type="text/css"> .x-toolbar > * { z-index: auto !important; } .x-toolbar .x-field-search { position: relative; } </style> Ext.application({ launch: function () { var popup = Ext.create("Ext.Panel", { width: 330, height: 230, scrollable: { direction: 'vertical', directionLock: true }, hidden: true, modal: true, hideOnMaskTap: true, top: 0, bottom: 0, items: [], listeners: { 'initialize': function () { var scroller = this.getScrollable().getScroller(); var sizeMonitors = scroller.sizeMonitors; var innerSizer = sizeMonitors.element; var containerSizer = sizeMonitors.container; // to demonstrate multiple scroller refreshes var refreshFn = scroller.refresh; scroller.refresh = function () { console.log('scroller refresh'); var t = Date.now(); refreshFn.call(scroller); var delta = Date.now() - t; console.log('scroller refresh took: ' + delta); } var doRefreshFn = scroller.doRefresh; scroller.doRefresh = function () { console.log('scroller doRefresh'); doRefreshFn.call(scroller); } // sizers have doRefresh in callback, to make them use the overriden version innerSizer.setCallback(scroller.doRefresh); containerSizer.setCallback(scroller.doRefresh); // to demonstrate multiple size detectors refreshes // content size detector var doInnerRefresh = innerSizer.refresh; innerSizer.refresh = function () { console.log('inner size detector refresh'); doInnerRefresh.call(innerSizer); } // container size detector var doContainerRefresh = containerSizer.refresh; containerSizer.refresh = function () { console.log('container size detector refresh'); doContainerRefresh.call(containerSizer); } } } }); var toolbar = Ext.create("Ext.Toolbar", { docked: 'top', scrollable: false, items: [ { xtype: 'spacer' }, { xtype: 'searchfield', placeHolder: 'Search', clearIcon: false, scrollable: false, listeners: { keyup: function () { var value = this.getValue(); if (value && value.length) { //------ if (!popup.rendered || popup.isHidden()) { var popupZIndex = popup.getZIndex(); this.inputZIndex = this.getZIndex(); this.setZIndex(popupZIndex); var t = Date.now(); popup.showBy(this); var delta = Date.now() - t; console.log('showBy took: ' + delta); } // ----- } else if (!popup.isHidden()) { //------ popup.hide(); this.setZIndex(this.inputZIndex); // ----- } } } } ] }); Ext.create("Ext.Panel", { fullscreen: true, scrollable: false, items: [ toolbar, { html: 'Some content' } ] }); Ext.Viewport.add(popup); } });
HELPFUL INFORMATION
We have performed some steps to improve the situation, maybe they will be helpful:- Add popup to Viewport on creation.
- It is not always needed for the popup to be signed to 'resize' event, it can be enough to use 'orientationchange' event.
- If the popup is supposed to be shown multiple times then 'alignTo' can be performed on 1st show and then only after 'resize'/'orientationchange' has happended.
- If the popup is supposed to be shown multiple times then there is no need to add/remove a mask each time but add it once and then show/hide instead. Plus as all popups are moved to Viewport than a single mask instance can be created under Viewport and reused by all popups.
Thank you in advance,
Regards
-
30 Apr 2012 11:54 AM #2Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 33,704
- Vote Rating
- 435
Thanks for the report.
I don't have this issue on my apps but I don't have iOS 4 devices either but we take performance very seriously.Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
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 almost in print!
When posting code, please use BBCode's CODE tags.
-
1 May 2012 8:19 AM #3Sencha - Sencha Touch Dev Team
- Join Date
- Mar 2007
- Location
- Redwood City, California
- Posts
- 3,653
- Vote Rating
- 14
Have you tried this with 2.0.1 yet? There were some changes that may have helped. We are working on additional changes that will be in 2.1.0 that will be more dramatic.
-
2 May 2012 5:12 AM #4
Hi,
Please see below some results of desktop Chrome 18.0, Safari 5.1.2 and iPad1 iOS4.5.3 tests.
I don't have iPad2 right now to check, will reply later.
--Sencha 2.0
On desktop the test case works faster, it takes 45-50ms for the 1st show, 15-30ms for subsequent shows both in Chrome and Safari. Also in both cases there are no multiple refreshes for popup scroller and size detectors.
The test case becomes slower and those multiple refreshes appear on iPads.
--Sencha 2.0.1 Final
In general the picture seems pretty the same for popups.
On desktop Chrome and Safari the test case takes 40-50ms and 15-30ms, no multiple refreshes.
On iPad1 these are 500-600ms and 50-100ms, multiple refresh are present.
For the real project on iPad1 it takes 1000-1100ms to show empty popup 1st time and 500-700ms on further attempts. Multiple refreshes are present as well.
Please let me know if you need any further details. Thanks.
Regards
-
3 May 2012 9:35 AM #5
Hi,
As promised, I've tested the case on IPad2 iOS 5.0.1, Sencha 2.0.1. It takes 50-70ms for the 1st show and 20-30ms for further attempts. No multiple refreshes are present. So they seem to appear on iOS4 only.
Just thought of one more case that might be more demonstrative. For this you can try TouchTweets example provided within the Sencha 2.0.1 final package. Only please replace its SearchBar.js with the below code:
With the default search list (20 items) popup is shown in 200-300ms. Scroll list to bottom to load one more page, try popup - it takes 300-400ms, with 4 pages loaded it takes about 600-700ms and so on...Code:Ext.define('Twitter.view.SearchBar', { extend: 'Ext.Toolbar', xtype: 'searchbar', requires: ['Ext.field.Text', 'Ext.field.Search'], config: { ui: 'searchbar', layout: 'vbox', cls: 'big', items: [ { xtype: 'title', title: 'Twitter Search' }, { xtype: 'searchfield', placeHolder: 'Search...', listeners: { keyup: function () { popup = this.popup; var value = this.getValue(); if (value && value.length) { if (!popup.rendered || popup.isHidden()) { var t = Date.now(); popup.showBy(this); var delta = Date.now() - t; console.log('showBy took: ' + delta); } } else if (!popup.isHidden()) { popup.hide(); } }, initialize: function () { this.popup = Ext.create("Ext.Panel", { width: 330, height: 230, scrollable: { direction: 'vertical', directionLock: true }, hidden: true, modal: true, hideOnMaskTap: true, top: 0, bottom: 0, items: [] }); } } } ] } });
Hope, this is helpful,
Regards,
Success! Looks like we've fixed this one. According to our records the fix was applied for
TOUCH-2866
in
2.1.


Reply With Quote