In Royale, by default any time you use “as”, the compiler will insert a “Language.as” function call to coerce the variable and it will become null if the variable is the wrong type.
While this ensures type safety and is sometimes useful, it can add overhead which can effect preforance particularly in places where it’s called a lot. In the framework code, I have tried to add @royaleignorecoercion where the coercion is not needed and @royaleemitcoercion where it is needed to be explicit about it. Those comment effect the behavior of the compiler. Using “assert" is much better for forcing specific types because those calls are optimized out in the release builds. HTH, Harbs > On Dec 21, 2023, at 11:14 AM, Maria Jose Esteve <mjest...@iest.com> wrote: > > Harb, can you explain to me the importance/need for @royaleignorecoercion? > > Hiedra > > -----Mensaje original----- > De: Harbs <harbs.li...@gmail.com> > Enviado el: jueves, 21 de diciembre de 2023 0:35 > Para: Apache Royale Development <dev@royale.apache.org> > Asunto: Re: (royale-asjs) branch develop updated: Added factory for reusing > data item renderers > > FYI, this class had a drastic effect on a tree I was working on. Expanding a > node went from taking between 1 and 2 seconds to taking about 20ms. > > I also committed a number of other performance optimizations relating > specifically to trees. It’s now possible to create a custom implementation > for getting the depth of nodes which is very expensive in the built-in method. > > Harbs > >> On Dec 21, 2023, at 1:31 AM, ha...@apache.org wrote: >> >> This is an automated email from the ASF dual-hosted git repository. >> >> harbs pushed a commit to branch develop in repository >> https://gitbox.apache.org/repos/asf/royale-asjs.git >> >> >> The following commit(s) were added to refs/heads/develop by this push: >> new 4e186b7442 Added factory for reusing data item renderers >> 4e186b7442 is described below >> >> commit 4e186b7442872764e27f086a3a03863f09c599aa >> Author: Harbs <ha...@in-tools.com> >> AuthorDate: Thu Dec 21 01:31:18 2023 +0200 >> >> Added factory for reusing data item renderers >> --- >> .../Basic/src/main/resources/basic-manifest.xml | 1 + >> .../projects/Basic/src/main/royale/BasicClasses.as | 1 + >> .../DataItemRendererFactoryForCollectionView.as | 2 + >> ...bleDataItemRendererFactoryForCollectionView.as} | 113 >> ++++++--------------- >> 4 files changed, 34 insertions(+), 83 deletions(-) >> >> diff --git >> a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml >> b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml >> index dc0d7bfd00..51a682c0e4 100644 >> --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml >> +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml >> @@ -228,6 +228,7 @@ >> <component id="DynamicUpdateItemRendererForArrayListData" >> class="org.apache.royale.html.beads.DynamicUpdateItemRendererForArrayListData"/> >> <component id="DataItemRendererFactoryForHierarchicalData" >> class="org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData" >> /> >> <component id="DataItemRendererFactoryForCollectionView" >> class="org.apache.royale.html.beads.DataItemRendererFactoryForCollecti >> onView" /> >> + <component id="ReusableDataItemRendererFactoryForCollectionView" >> + class="org.apache.royale.html.beads.ReusableDataItemRendererFactoryF >> + orCollectionView" /> >> <component id="SelectionDataItemRendererFactoryForCollectionView" >> class="org.apache.royale.html.beads.SelectionDataItemRendererFactoryForCollectionView" >> /> >> <component id="DynamicRemoveAllItemRendererForArrayListData" >> class="org.apache.royale.html.beads.DynamicRemoveAllItemRendererForArrayListData" >> /> >> <component id="DynamicRemoveAllByNullItemRendererForArrayListData" >> class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRenderer >> ForArrayListData" /> diff --git >> a/frameworks/projects/Basic/src/main/royale/BasicClasses.as >> b/frameworks/projects/Basic/src/main/royale/BasicClasses.as >> index f5591dcad6..91a45a7911 100644 >> --- a/frameworks/projects/Basic/src/main/royale/BasicClasses.as >> +++ b/frameworks/projects/Basic/src/main/royale/BasicClasses.as >> @@ -245,6 +245,7 @@ internal class BasicClasses >> import >> org.apache.royale.html.beads.DataItemRendererFactoryForArrayList; >> DataItemRendererFactoryForArrayList; >> import >> org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData; >> DataItemRendererFactoryForHierarchicalData; >> import >> org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView; >> DataItemRendererFactoryForCollectionView; >> + import >> +org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollec >> +tionView; ReusableDataItemRendererFactoryForCollectionView; >> import org.apache.royale.html.supportClasses.DataGroup; DataGroup; >> import org.apache.royale.html.supportClasses.Border; Border; >> import org.apache.royale.html.supportClasses.Viewport; Viewport; diff >> --git >> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/DataItemRendererFactoryForCollectionView.as >> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/DataItemRendererFactoryForCollectionView.as >> index de128b771e..07b387c7a0 100644 >> --- >> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/DataItemRendererFactoryForCollectionView.as >> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html >> +++ /beads/DataItemRendererFactoryForCollectionView.as >> @@ -77,6 +77,7 @@ package org.apache.royale.html.beads >> * @royaleignorecoercion >> org.apache.royale.collections.ICollectionView >> * @royaleignorecoercion >> org.apache.royale.core.IListPresentationModel >> * @royaleignorecoercion >> org.apache.royale.core.IIndexedItemRenderer >> + * @royaleignorecoercion >> +org.apache.royale.core.IIndexedItemRendererInitializer >> * @royaleignorecoercion >> org.apache.royale.core.IStrandWithModelView >> * @royaleignorecoercion org.apache.royale.html.beads.IListView >> */ >> @@ -152,6 +153,7 @@ package org.apache.royale.html.beads >> * @private >> * @royaleignorecoercion >> org.apache.royale.collections.ICollectionView >> * @royaleignorecoercion >> org.apache.royale.core.IIndexedItemRenderer >> + * @royaleignorecoercion >> +org.apache.royale.core.IIndexedItemRendererInitializer >> * @royaleignorecoercion >> org.apache.royale.core.IStrandWithModelView >> * @royaleignorecoercion org.apache.royale.html.beads.IListView >> */ >> diff --git >> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/DataItemRendererFactoryForCollectionView.as >> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/ReusableDataItemRendererFactoryForCollectionView.as >> similarity index 58% >> copy from >> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads >> /DataItemRendererFactoryForCollectionView.as >> copy to >> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads >> /ReusableDataItemRendererFactoryForCollectionView.as >> index de128b771e..d697b26632 100644 >> --- >> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea >> ds/DataItemRendererFactoryForCollectionView.as >> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html >> +++ /beads/ReusableDataItemRendererFactoryForCollectionView.as >> @@ -18,76 +18,55 @@ >> ////////////////////////////////////////////////////////////////////// >> ////////// >> package org.apache.royale.html.beads >> { >> + import org.apache.royale.utils.sendStrandEvent; >> + import org.apache.royale.events.CollectionEvent; >> + import org.apache.royale.core.IStrandWithModelView; >> import org.apache.royale.core.IIndexedItemRenderer; >> import org.apache.royale.core.IIndexedItemRendererInitializer; >> import org.apache.royale.core.IItemRendererOwnerView; >> - import org.apache.royale.core.IStrandWithModelView; >> - import org.apache.royale.events.CollectionEvent; >> - import org.apache.royale.events.Event; >> - import org.apache.royale.events.IEventDispatcher; >> - import org.apache.royale.html.beads.IListView; >> - import org.apache.royale.utils.sendStrandEvent; >> - >> /** >> - * This class creates itemRenderer instances from the data contained >> within an ICollectionView >> + * The ReusableDataItemRendererFactoryForCollectionView class will save >> removed itemRenderers >> + * and reuse them when new item renderers are needed. This is useful >> for large collections >> + * where creating new item renderers can be expensive. Using this class >> can drastically >> + * reduce rendering time at the expense of preventing the unused item >> renderers from being >> + * garbage collected. >> + * >> + * In an unscientific test, using this class reduced rendering time by >> about a factor of 100 in some cases. >> + * >> + * Item renderers must be able to be reused. Resetting the data >> property must properly reset the state and >> + * clean any event listeners from the old state. >> */ >> - public class DataItemRendererFactoryForCollectionView extends >> DataItemRendererFactoryBase >> + public class ReusableDataItemRendererFactoryForCollectionView >> +extends DataItemRendererFactoryForCollectionView >> { >> - public function >> DataItemRendererFactoryForCollectionView(target:Object = null) >> + public function >> +ReusableDataItemRendererFactoryForCollectionView(target:Object = >> +null) >> { >> super(target); >> } >> - >> - /** >> - * the dataProvider as a dispatcher >> - */ >> - protected var dped:IEventDispatcher; >> + >> + private var _unusedRenderers:Array = []; >> >> /** >> * @private >> * @royaleignorecoercion >> org.apache.royale.collections.ICollectionView >> * @royaleignorecoercion >> org.apache.royale.core.IListPresentationModel >> * @royaleignorecoercion >> org.apache.royale.core.IIndexedItemRenderer >> - * @royaleignorecoercion >> org.apache.royale.events.IEventDispatcher >> - */ >> - override protected function >> dataProviderChangeHandler(event:Event):void >> - { >> - super.dataProviderChangeHandler(event); >> - >> - if(dped) >> - { >> - >> dped.removeEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler); >> - >> dped.removeEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler); >> - >> dped.removeEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler); >> - dped = null; >> - } >> - >> - if (!dataProviderModel.dataProvider) >> - return; >> - >> - // listen for individual items being added in the >> future. >> - dped = dataProviderModel.dataProvider as >> IEventDispatcher; >> - dped.addEventListener(CollectionEvent.ITEM_ADDED, >> itemAddedHandler); >> - dped.addEventListener(CollectionEvent.ITEM_REMOVED, >> itemRemovedHandler); >> - dped.addEventListener(CollectionEvent.ITEM_UPDATED, >> itemUpdatedHandler); >> - } >> - >> - /** >> - * @private >> - * @royaleignorecoercion >> org.apache.royale.collections.ICollectionView >> - * @royaleignorecoercion >> org.apache.royale.core.IListPresentationModel >> - * @royaleignorecoercion >> org.apache.royale.core.IIndexedItemRenderer >> + * @royaleignorecoercion >> +org.apache.royale.core.IIndexedItemRendererInitializer >> * @royaleignorecoercion >> org.apache.royale.core.IStrandWithModelView >> * @royaleignorecoercion org.apache.royale.html.beads.IListView >> */ >> - protected function itemAddedHandler(event:CollectionEvent):void >> + override protected function >> +itemAddedHandler(event:CollectionEvent):void >> { >> if(!dataProviderExist) >> return; >> var view:IListView = (_strand as >> IStrandWithModelView).view as IListView; >> var dataGroup:IItemRendererOwnerView = view.dataGroup; >> >> - var ir:IIndexedItemRenderer = >> itemRendererFactory.createItemRenderer() as IIndexedItemRenderer; >> + var ir:IIndexedItemRenderer; >> + if(_unusedRenderers.length > 0) >> + ir = _unusedRenderers.pop(); >> + >> + else >> + ir = itemRendererFactory.createItemRenderer() >> as >> +IIndexedItemRenderer; >> >> var data:Object = event.item; >> dataGroup.addItemRendererAt(ir, event.index); @@ -108,7 >> +87,8 @@ >> package org.apache.royale.html.beads >> } >> >> sendStrandEvent(_strand,"itemsCreated"); >> - sendStrandEvent(_strand,"layoutNeeded"); >> + // The itemsCreated handler sends layoutNeeded, so no >> need to do it here. >> + // sendStrandEvent(_strand,"layoutNeeded"); >> } >> >> /** >> @@ -119,7 +99,7 @@ package org.apache.royale.html.beads >> * @royaleignorecoercion >> org.apache.royale.core.IStrandWithModelView >> * @royaleignorecoercion org.apache.royale.html.beads.IListView >> */ >> - protected function >> itemRemovedHandler(event:CollectionEvent):void >> + override protected function >> +itemRemovedHandler(event:CollectionEvent):void >> { >> if(!dataProviderExist) >> return; >> @@ -130,7 +110,7 @@ package org.apache.royale.html.beads >> var ir:IIndexedItemRenderer = >> dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer; >> if (!ir) return; // may have already been cleaned up, >> possibly when a tree node closes >> dataGroup.removeItemRenderer(ir); >> - >> + _unusedRenderers.push(ir); >> // adjust the itemRenderers' index to adjust for the >> shift >> var n:int = dataGroup.numItemRenderers; >> for (var i:int = event.index; i < n; i++) @@ -147,39 >> +127,6 @@ >> package org.apache.royale.html.beads >> >> sendStrandEvent(_strand,"layoutNeeded"); >> } >> - >> - /** >> - * @private >> - * @royaleignorecoercion >> org.apache.royale.collections.ICollectionView >> - * @royaleignorecoercion >> org.apache.royale.core.IIndexedItemRenderer >> - * @royaleignorecoercion >> org.apache.royale.core.IStrandWithModelView >> - * @royaleignorecoercion org.apache.royale.html.beads.IListView >> - */ >> - protected function >> itemUpdatedHandler(event:CollectionEvent):void >> - { >> - if(!dataProviderExist) >> - return; >> - >> - var view:IListView = (_strand as >> IStrandWithModelView).view as IListView; >> - var dataGroup:IItemRendererOwnerView = view.dataGroup; >> - >> - // update the given renderer with (possibly) new >> information so it can change its >> - // appearence or whatever. >> - var ir:IIndexedItemRenderer = >> dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer; >> - >> - var data:Object = event.item; >> - (itemRendererInitializer as >> IIndexedItemRendererInitializer).initializeIndexedItemRenderer(ir, data, >> event.index); >> - ir.data = data; >> - } >> - >> - override protected function get dataProviderLength():int >> - { >> - return dataProviderModel.dataProvider.length; >> - } >> - >> - override protected function getItemAt(i:int):Object >> - { >> - return dataProviderModel.dataProvider.getItemAt(i); >> - } >> + >> } >> } >> \ No newline at end of file >> >