Yeah, I was thinking along those lines. However, it's interesting that in tests Vector 0a vs Vector 1a, the implicit cast is still faster than using [ ] to access the reference directly from the vector. You'd think that with the vector being typed as TestClass, vector[i].someMethod() should be faster than var reference:TestClass = vector[i]; reference.someMethod()
Unless you were then going to use the reference again, in which case storing a temporary reference will always be faster. But for a one time look up from a typed vector, I'm surprised that two lines of code executes faster than one. I was wondering whether there might be something wrong with my test, but I can't see anything. Piers On 27 Dec 2009, at 14:05, Paul Andrews wrote: > Piers Cowburn wrote: >> Cool, looks like the implicit cast is faster across the board, and almost >> twice as fast as just using the array access operator. >> > For an object of a known class, I think the compiler is just referring > directly to the method rather than looking it up. When a method is invoked on > an abstract object it has to look at the class info for the object to locate > the method AT RUNTIME - hence the overhead. When the class is known it can > call the method directly without a runtime lookup. > > In the case of the explicit cast, I would expect that the cast is pointless > and adding needless overhead since the method reference is using the method > lookup at compile time from the variable, not from the cast. The cast adds > needless overhead at run time. > > Paul >> >> On 27 Dec 2009, at 13:13, Cor wrote: >> >> >>> With this, my results are: >>> Starting tests... >>> [Array 0a] Array access test: 462 >>> [Array 1a] Implicit cast test: 258 >>> [Array 2a] Explicit cast test: 406 >>> [Array 3a] As cast test: 429 >>> [Array 0b] Array access test (two operations): 1062 >>> [Array 1b] Implicit cast test (two operations): 477 >>> [Array 2b] Explicit cast test (two operations): 647 >>> [Array 3b] As cast test (two operations): 652 >>> [Vector 0a] Vector access test: 458 >>> [Vector 1a] Implicit cast test: 252 >>> [Vector 2a] Explicit cast test: 402 >>> [Vector 3a] As cast test: 425 >>> [Vector 0b] Vector access test (two operations): 1034 >>> [Vector 1b] Implicit cast test (two operations): 483 >>> [Vector 2b] Explicit cast test (two operations): 624 >>> [Vector 3b] As cast test (two operations): 679 >>> >>> -----Original Message----- >>> From: [email protected] >>> [mailto:[email protected]] On Behalf Of Piers >>> Cowburn >>> Sent: zondag 27 december 2009 14:07 >>> To: Flash Coders List >>> Subject: Re: [Flashcoders] Performance from casting array/vector? >>> >>> Hi Cor, >>> >>> This was my test class, just a couple of dummy methods that do a variable >>> declaration and an increment: >>> >>> package { /** >>> * Internal test class >>> */ >>> public class TestClass >>> { >>> public function someMethod():void >>> { >>> var i:int = 0; >>> i++; >>> } >>> >>> public function someOtherMethod():void >>> { >>> var i:int = 0; >>> i++; >>> } >>> } >>> } >>> >>> >>> Piers >>> >>> >>> On 27 Dec 2009, at 11:52, Cor wrote: >>> >>> >>>> Hi piers, >>>> >>>> I am trying to follow your topic. >>>> What is in your TestClass.as?? >>>> >>>> Kind regards >>>> Cor >>>> >>>> -----Original Message----- >>>> From: [email protected] >>>> [mailto:[email protected]] On Behalf Of Piers >>>> Cowburn >>>> Sent: zondag 27 december 2009 12:35 >>>> To: Flash Coders List >>>> Subject: Re: [Flashcoders] Performance from casting array/vector? >>>> >>>> Hi Steve, >>>> >>>> I thought it'd be useful to have some actual figures, so I put together a >>>> quick test. Test code was as follows: >>>> >>>> package { >>>> import flash.display.Sprite; >>>> import flash.utils.getTimer; >>>> /** >>>> * @author Piers Cowburn >>>> */ >>>> public class ArrayAccessTest extends Sprite { >>>> private const ITERATIONS:int = 1000000; >>>> >>>> public function ArrayAccessTest() >>>> { trace("Starting tests..."); >>>> >>>> var startTimer:int; >>>> var i:int; >>>> var j:int; >>>> >>>> var array:Array = [new TestClass(), new TestClass(), new >>>> TestClass()]; >>>> var vector:Vector.<TestClass> = new Vector.<TestClass>(); >>>> vector.push(new TestClass()); >>>> vector.push(new TestClass()); >>>> vector.push(new TestClass()); >>>> var numItems:int = array.length; >>>> var implicitCast:TestClass; >>>> var explicitCast:TestClass; >>>> var asCast:TestClass; >>>> >>>> // >>>> // [Array 0a] Array access test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> array[j].someMethod(); >>>> } >>>> } trace("[Array 0a] Array access test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 1a] Implicit cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> implicitCast = array[j]; >>>> implicitCast.someMethod(); >>>> } >>>> } trace("[Array 1a] Implicit cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 2a] Explicit cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> explicitCast = TestClass(array[j]); >>>> explicitCast.someMethod(); >>>> } >>>> } trace("[Array 2a] Explicit cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 3a] As cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> asCast = array[j] as TestClass; >>>> asCast.someMethod(); >>>> } >>>> } trace("[Array 3a] As cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 0b] Array access test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> array[j].someMethod(); >>>> array[j].someOtherMethod(); >>>> } >>>> } trace("[Array 0b] Array access test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 1b] Implicit cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> implicitCast = array[j]; >>>> implicitCast.someMethod(); >>>> implicitCast.someOtherMethod(); >>>> } >>>> } trace("[Array 1b] Implicit cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 2b] Explicit cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> explicitCast = TestClass(array[j]); >>>> explicitCast.someMethod(); >>>> explicitCast.someOtherMethod(); >>>> } >>>> } trace("[Array 2b] Explicit cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Array 3b] As cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> asCast = array[j] as TestClass; >>>> asCast.someMethod(); >>>> asCast.someOtherMethod(); >>>> } >>>> } trace("[Array 3b] As cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> >>>> >>>> // >>>> // [Vector 0a] Vector access test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> vector[j].someMethod(); >>>> } >>>> } trace("[Vector 0a] Vector access test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 1a] Implicit cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> implicitCast = vector[j]; >>>> implicitCast.someMethod(); >>>> } >>>> } trace("[Vector 1a] Implicit cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 2a] Explicit cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> explicitCast = TestClass(vector[j]); >>>> explicitCast.someMethod(); >>>> } >>>> } trace("[Vector 2a] Explicit cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 3a] As cast test >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> asCast = vector[j] as TestClass; >>>> asCast.someMethod(); >>>> } >>>> } trace("[Vector 3a] As cast test: " + >>>> (getTimer()-startTimer)); >>>> >>>> >>>> // >>>> // [Vector 0b] Vector access test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> vector[j].someMethod(); >>>> vector[j].someOtherMethod(); >>>> } >>>> } trace("[Vector 0b] Vector access test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 1b] Implicit cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> implicitCast = vector[j]; >>>> implicitCast.someMethod(); >>>> implicitCast.someOtherMethod(); >>>> } >>>> } trace("[Vector 1b] Implicit cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 2b] Explicit cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> explicitCast = TestClass(vector[j]); >>>> explicitCast.someMethod(); >>>> explicitCast.someOtherMethod(); >>>> } >>>> } trace("[Vector 2b] Explicit cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> >>>> // >>>> // [Vector 3b] As cast test (two operations) >>>> startTimer = getTimer(); >>>> for (i = 0; i < ITERATIONS; ++i) >>>> { >>>> for (j = 0; j < numItems; ++j) >>>> { >>>> asCast = vector[j] as TestClass; >>>> asCast.someMethod(); >>>> asCast.someOtherMethod(); >>>> } >>>> } trace("[Vector 3b] As cast test (two >>>> operations): " + >>>> (getTimer()-startTimer)); >>>> } >>>> } >>>> } >>>> >>>> And the results were: >>>> >>>> [Array 0a] Array access test: 1631 >>>> [Array 1a] Implicit cast test: 1527 >>>> [Array 2a] Explicit cast test: 1689 >>>> [Array 3a] As cast test: 1745 >>>> [Array 0b] Array access test (two operations): 3172 >>>> [Array 1b] Implicit cast test (two operations): 2636 >>>> [Array 2b] Explicit cast test (two operations): 2817 >>>> [Array 3b] As cast test (two operations): 2841 >>>> [Vector 0a] Vector access test: 1624 >>>> [Vector 1a] Implicit cast test: 1520 >>>> [Vector 2a] Explicit cast test: 1707 >>>> [Vector 3a] As cast test: 1722 >>>> [Vector 0b] Vector access test (two operations): 3160 >>>> [Vector 1b] Implicit cast test (two operations): 2638 >>>> [Vector 2b] Explicit cast test (two operations): 2790 >>>> [Vector 3b] As cast test (two operations): 2828 >>>> >>>> >>>> I was surprised to see that using an implicit cast was fastest in all >>>> situations, even faster than using the array access operator to make one >>>> method call (test Array 0a vs. Array 1b). Also, you can see that storing a >>>> temporary variable really starts to make a difference when you're making >>>> more than one method call (difference between Array 0b and Array 1b). >>>> >>>> HTH, >>>> Piers >>>> >>>> >>>> On 27 Dec 2009, at 01:26, Piers Cowburn wrote: >>>> >>>> >>>>> *Disclaimer* This is un-benchmarked, but it's what I usually work to! If >>>>> >>>> anyone has any corrections re. speed, I'd be glad to hear them :) >>>> >>>>> AFAIK, using implicit casting rather than explicit in this case is >>>>> >>> faster, >>> >>>> so A1 in your examples is faster than A2. Also, it's better to move your >>>> variable declaration outside the loop: >>>> >>>>> var i:int = myArray.length; >>>>> // Variable is declared once here and then reused >>>>> var myClass:MyClass; >>>>> while (i--) >>>>> { >>>>> myClass = myArray[i]; >>>>> } >>>>> >>>>> >>>>> With vectors, you don't need to cast at all. However, though you can >>>>> >>>> access your references directly from the vector using [ ], like you've >>>> >>> done >>> >>>> in V3, it will be faster to store a local reference if you're using it >>>> >>> more >>> >>>> than once. So for example: >>>> >>>>> var i:int = myVector.length; >>>>> var myClass:MyClass; >>>>> while (i--) >>>>> { >>>>> // Store the reference in a temporary variable to avoid using [ ] >>>>> >>>> unnecessarily >>>> >>>>> myClass = myVector[i]; >>>>> myClass.someMethod(); >>>>> myClass.someOtherMethod(); >>>>> } >>>>> >>>>> will be faster than: >>>>> >>>>> var i:int = myVector.length; >>>>> while (i--) >>>>> { >>>>> // This uses [ ] twice >>>>> myVector[i].someMethod(); >>>>> myVector[i].someOtherMethod(); >>>>> } >>>>> >>>>> >>>>> If you're only using the reference once though, it should be faster just >>>>> >>>> to use [ ], so: >>>> >>>>> var i:int = myVector.length; >>>>> while (i--) >>>>> { >>>>> // Just using the reference once, so not defining a temporary variable: >>>>> myVector[i].someMethod(); >>>>> } >>>>> >>>>> will be faster than: >>>>> >>>>> var i:int = myVector.length; >>>>> var myClass:MyClass; >>>>> while (i--) >>>>> { >>>>> // This is a waste as we're only using it once >>>>> myClass = myVector[i]; >>>>> myClass.someMethod(); >>>>> } >>>>> >>>>> >>>>> As I said, I don't have benchmarked figures for these, so don't take it >>>>> >>> as >>> >>>> gospel, but I think this was what I read when I read it. >>>> >>>>> Piers >>>>> >>>>> >>>>> >>>>> >>>>> On 27 Dec 2009, at 00:24, Steven Sacks wrote: >>>>> >>>>> >>>>>> var instance1:MyClass = new MyClass(); >>>>>> var instance2:MyClass = new MyClass(); >>>>>> var instance3:MyClass = new MyClass(); >>>>>> >>>>>> var myArray:Array = [instance1, instance2, instance3]; >>>>>> >>>>>> // QUESTION A: CASTING WITH ARRAYS >>>>>> >>>>>> var i:int = myArray.length; >>>>>> while (i--) >>>>>> { >>>>>> // [A1] - Does Flash have to do a look up here? >>>>>> var myClass:MyClass = myArray[i]; >>>>>> >>>>>> // [A2] - Does casting it like this boost performance >>>>>> var myClass:MyClass = MyClass(myArray[i]); >>>>>> >>>>>> // [A3] - I know using "as" is slower than direct casting >>>>>> var myClass:MyClass = myArray[i] as MyClass; >>>>>> } >>>>>> >>>>>> // QUESTION B: CASTING WITH VECTORS >>>>>> >>>>>> var myVector:Vector.<MyClass> = Vector.<MyClass>(myArray); >>>>>> >>>>>> var i:int = myVector.length; >>>>>> >>>>>> while (i--) >>>>>> { >>>>>> // [V1] - Will this avoid the lookup? >>>>>> var myClass:MyClass = myVector[i]; >>>>>> >>>>>> // [V2] - Or do I need to cast here even though it's a Vector? >>>>>> var myClass:MyClass = MyClass(myVector[i]); >>>>>> >>>>>> // [V3] - And if so, can I do this without a lookup? >>>>>> myVector[i].someMethod(); >>>>>> >>>>>> // [V4] - Or do I need to do this? >>>>>> MyClass(myVector[i]).someMethod(); >>>>>> } >>>>>> >>>>>> >>>>>> Thanks in advance for anyone who can shed some light here. I believe >>>>>> >>>> A2/V2 is "fastest" but I'm not certain, and I also don't know if it's >>>> required for Vector. >>>> >>>>>> _______________________________________________ >>>>>> Flashcoders mailing list >>>>>> [email protected] >>>>>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>>>>> >>>>> _______________________________________________ >>>>> Flashcoders mailing list >>>>> [email protected] >>>>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>>>> >>>> _______________________________________________ >>>> Flashcoders mailing list >>>> [email protected] >>>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>>> No virus found in this incoming message. >>>> Checked by AVG - www.avg.com Version: 9.0.722 / Virus Database: >>>> 270.14.119/2586 - Release Date: >>>> >>> 12/26/09 >>> >>>> 20:02:00 >>>> >>>> _______________________________________________ >>>> Flashcoders mailing list >>>> [email protected] >>>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>>> >>> _______________________________________________ >>> Flashcoders mailing list >>> [email protected] >>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>> No virus found in this incoming message. >>> Checked by AVG - www.avg.com Version: 9.0.722 / Virus Database: >>> 270.14.120/2588 - Release Date: 12/26/09 >>> 20:02:00 >>> >>> _______________________________________________ >>> Flashcoders mailing list >>> [email protected] >>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>> >> >> >> _______________________________________________ >> Flashcoders mailing list >> [email protected] >> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >> >> > > _______________________________________________ > Flashcoders mailing list > [email protected] > http://chattyfig.figleaf.com/mailman/listinfo/flashcoders _______________________________________________ Flashcoders mailing list [email protected] http://chattyfig.figleaf.com/mailman/listinfo/flashcoders

