You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ha...@apache.org on 2018/03/24 20:52:34 UTC

[royale-asjs] branch feature/layout-optimization created (now 6461d5b)

This is an automated email from the ASF dual-hosted git repository.

harbs pushed a change to branch feature/layout-optimization
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git.


      at 6461d5b  Major performance increase

This branch includes the following new commits:

     new 6461d5b  Major performance increase

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
harbs@apache.org.

[royale-asjs] 01/01: Major performance increase

Posted by ha...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

harbs pushed a commit to branch feature/layout-optimization
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git

commit 6461d5b1b40570c18277899c159ee2101f7d9f8f
Author: Harbs <ha...@in-tools.com>
AuthorDate: Sat Mar 24 23:52:15 2018 +0300

    Major performance increase
    
    I’m seeing about a 5 *times* performance improvement with this
    (~150 ms layout now takes ~30 ms)
---
 .../royale/org/apache/royale/core/LayoutBase.as    | 51 +++++++------
 .../royale/org/apache/royale/core/LayoutManager.as | 84 ++++++++++++++++++++++
 .../main/royale/org/apache/royale/core/UIBase.as   | 35 +++++++++
 .../royale/org/apache/royale/core/UIButtonBase.as  | 31 ++++++++
 .../projects/Core/src/main/royale/CoreClasses.as   |  1 +
 .../royale/org/apache/royale/core/ILayoutChild.as  | 24 +++++++
 .../org/apache/royale/utils/measureComponent.as    | 27 +++++++
 7 files changed, 232 insertions(+), 21 deletions(-)

diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutBase.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutBase.as
index 97ac19a..7a4f95f 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutBase.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutBase.as
@@ -30,10 +30,12 @@ package org.apache.royale.core
     import org.apache.royale.core.IUIBase;
     import org.apache.royale.core.layout.EdgeData;
     import org.apache.royale.core.layout.MarginData;
+	import org.apache.royale.core.LayoutManager;
 	import org.apache.royale.core.ValuesManager;
 	import org.apache.royale.events.IEventDispatcher;
 	import org.apache.royale.events.Event;
     import org.apache.royale.utils.CSSUtils;
+	import org.apache.royale.utils.measureComponent;
 
     /**
      *  This class is the base class for most, if not all, layouts. 
@@ -302,6 +304,8 @@ package org.apache.royale.core
          *  @playerversion Flash 10.2
          *  @playerversion AIR 2.6
          *  @productversion Royale 0.8
+		 * @royaleignorecoercion org.apache.royale.core.ILayoutParent
+		 * @royaleignorecoercion org.apache.royale.core.UIBase
 		 */
 		public function performLayout():void
 		{
@@ -309,31 +313,36 @@ package org.apache.royale.core
 			if (isLayoutRunning) return;
 			
 			isLayoutRunning = true;
-
-			var oldWidth:Number = host.width;
-			var oldHeight:Number = host.height;
+			LayoutManager.addMeasurement(host);
+			// measureComponent(host);
+			// var oldWidth:Number = host.measuredWidth;
+			// var oldHeight:Number = host.measuredHeight;
 			
 			var viewBead:ILayoutHost = (host as ILayoutParent).getLayoutHost();
 			
 			viewBead.beforeLayout();
-			
-			if (layout()) {
-				viewBead.afterLayout();
-			}
-			
-			isLayoutRunning = false;
-			
-			IEventDispatcher(host).dispatchEvent(new Event("layoutComplete"));
-			
-			// check sizes to see if layout changed the size or not
-			// and send an event to re-layout parent of host
-			if (host.width != oldWidth ||
-			    host.height != oldHeight)
-			{
-				isLayoutRunning = true;
-				host.dispatchEvent(new Event("sizeChanged"));
-				isLayoutRunning = false;
-			}
+			LayoutManager.addLayout(
+				function ():void
+				{
+					if (layout()) {
+						viewBead.afterLayout();
+					}
+					
+					isLayoutRunning = false;
+					
+					IEventDispatcher(host).dispatchEvent(new Event("layoutComplete"));
+					
+					// check sizes to see if layout changed the size or not
+					// and send an event to re-layout parent of host
+					if (host.width != host.measuredWidth ||
+						host.height != host.measuredHeight)
+					{
+						isLayoutRunning = true;
+						host.dispatchEvent(new Event("sizeChanged"));
+						isLayoutRunning = false;
+					}
+				}
+			);
 
 		}
 
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutManager.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutManager.as
new file mode 100644
index 0000000..ce6b8ad
--- /dev/null
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/LayoutManager.as
@@ -0,0 +1,84 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "Licens"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.core
+{
+    COMPILE::SWF
+    {
+        import flash.utils.setTimeout;
+    }
+    import org.apache.royale.utils.measureComponent;
+
+    public class LayoutManager
+    {
+        static private var layoutPending:Boolean;
+        static private var measurementPending:Boolean;
+        static private var measurements:Array = [];
+        static public function addMeasurement(component:ILayoutChild):void
+        {
+            measurements.push(component);
+            COMPILE::SWF
+            {
+                if(!measurementPending)
+                {
+                    measurementPending = true;
+                    setTimeout(executeMeasurements, 0);
+                }
+            }
+
+            COMPILE::JS
+            {
+                if(!measurementPending)
+                {
+                    measurementPending = true;
+                    requestAnimationFrame(executeMeasurements);
+                }
+            }
+        }
+        static private var pendingLayouts:Array = [];
+        static public function addLayout(callback:Function):void
+        {
+            pendingLayouts.push(callback);
+            if(!layoutPending && !measurementPending)
+            {
+                layoutPending = true;
+                setTimeout(executeLayouts, 0);
+            }
+        }
+        static private function executeMeasurements():void
+        {
+            
+            measurementPending = false;
+            while(measurements.length)
+            {
+                var component:ILayoutChild = measurements.shift();
+                measureComponent(component);
+            }
+            executeLayouts();
+        }
+        static private function executeLayouts():void
+        {
+            while(pendingLayouts.length)
+            {
+                var callback:Function  = pendingLayouts.shift();
+                callback();
+            }
+            layoutPending = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIBase.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIBase.as
index 77ed10b..2e2c777 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIBase.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIBase.as
@@ -395,6 +395,8 @@ package org.apache.royale.core
         COMPILE::JS
         public function get width():Number
         {
+            if(!isNaN(_explicitWidth))
+                return _explicitWidth;
             var pixels:Number;
             var strpixels:String = element.style.width as String;
             if(strpixels == null)
@@ -487,6 +489,8 @@ package org.apache.royale.core
         COMPILE::JS
         public function get height():Number
         {
+            if(!isNaN(_explicitHeight))
+                return _explicitHeight;
             var pixels:Number;
             var strpixels:String = element.style.height as String;
             if(strpixels == null)
@@ -589,6 +593,37 @@ package org.apache.royale.core
                     dispatchEvent(new Event("widthChanged"));
             }
         }
+
+        /**
+         * @private
+         * Used by layout to prevent causing unnecessary reflows when measuring.
+         */
+        private var _measuredWidth:Number;
+
+		public function get measuredWidth():Number
+		{
+			return _measuredWidth;
+		}
+
+		public function set measuredWidth(value:Number):void
+		{
+			_measuredWidth = value;
+		}
+        /**
+         * @private
+         * Used by layout to prevent causing unnecessary reflows when measuring.
+         */
+        private var _measuredHeight:Number;
+
+		public function get measuredHeight():Number
+		{
+			return _measuredHeight;
+		}
+
+		public function set measuredHeight(value:Number):void
+		{
+			_measuredHeight = value;
+		}
         
         /**
          *  @copy org.apache.royale.core.ILayoutChild#setWidthAndHeight
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIButtonBase.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIButtonBase.as
index 75c68ef..51492cf 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIButtonBase.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/UIButtonBase.as
@@ -394,6 +394,37 @@ package org.apache.royale.core
 		}
 
         /**
+         * @private
+         * Used by layout to prevent causing unnecessary reflows when measuring.
+         */
+        private var _measuredWidth:Number;
+
+		public function get measuredWidth():Number
+		{
+			return _measuredWidth;
+		}
+
+		public function set measuredWidth(value:Number):void
+		{
+			_measuredWidth = value;
+		}
+        /**
+         * @private
+         * Used by layout to prevent causing unnecessary reflows when measuring.
+         */
+        private var _measuredHeight:Number;
+
+		public function get measuredHeight():Number
+		{
+			return _measuredHeight;
+		}
+
+		public function set measuredHeight(value:Number):void
+		{
+			_measuredHeight = value;
+		}
+
+        /**
          *  @copy org.apache.royale.core.IUIBase#setHeight
          *  
          *  @langversion 3.0
diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as b/frameworks/projects/Core/src/main/royale/CoreClasses.as
index 2ec8859..22b0c3e 100644
--- a/frameworks/projects/Core/src/main/royale/CoreClasses.as
+++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as
@@ -235,6 +235,7 @@ internal class CoreClasses
 	import org.apache.royale.debugging.notNull; notNull;
 	import org.apache.royale.debugging.throwError; throwError;
 
+	import org.apache.royale.utils.measureComponent; measureComponent;
 	import org.apache.royale.utils.loadBeadFromValuesManager; loadBeadFromValuesManager;
 
 	import org.apache.royale.utils.array.rangeCheck; rangeCheck;
diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/core/ILayoutChild.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/core/ILayoutChild.as
index 439190b..8d39cc4 100755
--- a/frameworks/projects/Core/src/main/royale/org/apache/royale/core/ILayoutChild.as
+++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/core/ILayoutChild.as
@@ -81,6 +81,30 @@ package org.apache.royale.core
          */
         function get explicitHeight():Number;
         function set explicitHeight(value:Number):void;
+
+        /**
+         *  The measured width of this component 
+         *  This value can be cached by layouts to prevent reflow caused by measuring
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.3
+         */
+        function get measuredWidth():Number;
+        function set measuredWidth(value:Number):void;
+        
+        /**
+         *  The measured height of this component 
+         *  This value can be cached by layouts to prevent reflow caused by measuring
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10.2
+         *  @playerversion AIR 2.6
+         *  @productversion Royale 0.9.3
+         */
+        function get measuredHeight():Number;
+        function set measuredHeight(value:Number):void;
         
         /**
          * Sets the height of the component without
diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/measureComponent.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/measureComponent.as
new file mode 100644
index 0000000..3132eec
--- /dev/null
+++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/measureComponent.as
@@ -0,0 +1,27 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "Licens"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.utils
+{
+    import org.apache.royale.core.ILayoutChild
+    public function measureComponent(component:ILayoutChild):void
+    {
+        component.measuredWidth = component.width;
+        component.measuredHeight = component.height;
+    }
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
harbs@apache.org.