My undestanding is that push should be slower than accessing the index directly, but take that as "common sense": a function call should involve a bit more processing, but I don't know the specifics. I do know that both compiles to different bytecode. Off the top of my head, it was 4 ops, something like
push value push index push theobject setproperty ==> theobject[index] = value Making a push involves a callProperty operation, where you pass the object, the method and the arguments. Maybe it's the same number of operations, but I think the call operation is a bit more complex internally, as it creates a new frame on the stack, it has to pass the arguments, executes the function, clears the stack frame and then returns back to the callee. For disassembling, I'm using abcdump, a tool that is included in the Tamarin project. You can find a compiled version for Windows and use instructions here (though it's super easy to use): http://iteratif.free.fr/blog/index.php?2006/11/15/61-un-premier-decompileur-as3 It's in french, but looking at the text added to your reply, I assume you'll have not problems with that ;) Another post about the subject, in English http://www.5etdemi.com/blog/archives/2007/01/as3-decompiler/ Cheers Juan Pablo Califano 2008/7/30, laurent <[EMAIL PROTECTED]>: > > Hm yes, there's no difference between For and while. > What do you think about a[ a.length ] and a.push(); ? > > How did you get the decompiles function ? > > Thanks for pushing it. > L > > Juan Pablo Califano a écrit : > >> I'd take these results with a pinch of salt. I don't think they're >> conclusive, since one test seems to affect the performance of the others >> (and we are talking about really small differences anyway, which I think >> could be attributed to other factors than the tested code itself). >> >> Let's take, for instance the for / while tests. If I run all your tests, I >> get results similar to yours. >> >> takeLengthPlusOut : 1958 >> takeForWithLengthPlus : 1788 >> >> However, if I run just those two tests the results change. And if I alter >> the order in which the tests are run, the first one always seems to take >> less time. >> // running just these two, tracing the results in the same order the loops >> are executed >> >> takeLengthPlusOut : 1876 >> takeForWithLengthPlus : 2003 >> >> takeLengthPlusOut : 1876 >> takeForWithLengthPlus : 1935 >> >> takeForWithLengthPlus : 1874 >> takeLengthPlusOut : 1946 >> >> takeForWithLengthPlus : 1861 >> takeLengthPlusOut : 1935 >> I think this particular for / while case is very illustrative of some >> external bias, because the execution order consistently affects the >> results >> and because if you disassemble both loops, they're nearly identical. The >> only difference is the order in which one operation previous to the loop >> is >> executed (it's not even the "body" of the loop or its conditional test). >> >> >> FOR: >> >> function takeForWithLengthPlus():String /* disp_id 0*/ >> { >> // local_count=4 max_scope=1 max_stack=3 code_len=61 >> 0 getlocal0 >> 1 pushscope >> 2 pushbyte 0 >> 4 setlocal1 >> 5 pushnull >> 6 coerce Array >> 8 setlocal2 >> 9 pushnan >> 10 setlocal3 >> 11 findpropstrict Array >> 13 constructprop Array (0) >> 16 coerce Array >> 18 setlocal2 >> 19 findpropstrict flash.utils::getTimer >> 21 callproperty flash.utils::getTimer (0) >> 24 convert_d >> 25 setlocal3 >> 26 pushbyte 0 >> 28 setlocal1 >> 29 jump L1 >> >> >> L2: >> 33 label >> 34 getlocal2 >> 35 getlocal2 >> 36 getproperty length >> 38 getlocal1 >> 39 setproperty null >> 41 inclocal_i 1 >> >> L1: >> 43 getlocal1 >> 44 pushint 10000000 // 0x989680 >> 46 iflt L2 >> >> 50 pushstring "takeForWithLengthPlus : " >> 52 findpropstrict flash.utils::getTimer >> 54 callproperty flash.utils::getTimer (0) >> 57 getlocal3 >> 58 subtract >> 59 add >> 60 returnvalue >> } >> >> >> WHILE: >> >> function takeLengthPlusOut():String /* disp_id 0*/ >> { >> // local_count=4 max_scope=1 max_stack=3 code_len=61 >> 0 getlocal0 >> 1 pushscope >> 2 pushbyte 0 >> 4 setlocal1 >> 5 pushnull >> 6 coerce Array >> 8 setlocal2 >> 9 pushnan >> 10 setlocal3 >> 11 pushbyte 0 >> 13 setlocal1 >> 14 findpropstrict Array >> 16 constructprop Array (0) >> 19 coerce Array >> 21 setlocal2 >> 22 findpropstrict flash.utils::getTimer >> 24 callproperty flash.utils::getTimer (0) >> 27 convert_d >> 28 setlocal3 >> 29 jump L1 >> >> >> L2: >> 33 label >> 34 getlocal2 >> 35 getlocal2 >> 36 getproperty length >> 38 getlocal1 >> 39 setproperty null >> 41 inclocal_i 1 >> >> L1: >> 43 getlocal1 >> 44 pushint 10000000 // 0x989680 >> 46 iflt L2 >> >> 50 pushstring "takeLengthPlusOut : " >> 52 findpropstrict flash.utils::getTimer >> 54 callproperty flash.utils::getTimer (0) >> 57 getlocal3 >> 58 subtract >> 59 add >> 60 returnvalue >> } >> The only difference is that in the foor loop, i = 0 is run immediately >> before testing i against 10000000: >> >> 26 pushbyte 0 >> 28 setlocal1 >> >> whereas in the while loop, that assignment is executed before constructing >> the array: >> >> 11 pushbyte 0 >> 13 setlocal1 >> >> >> Cheers >> Juan Pablo Califano >> >> 2008/7/29, laurent <[EMAIL PROTECTED]>: >> >> >>> Hi, >>> >>> I often asked myself if a[ a.length ] = xxx was faster or slower then >>> a.push( xxx ), I did some test at wake up, fresh with coffee. >>> So now I know the answer and I got a bit more about while and for, and >>> more >>> obvious about using them with decremental or incremental counters. >>> >>> from results, > means faster : >>> >>> for > while ....hey yes...oO >>> increment > decrement >>> length > push >>> increment or certainly make any number operation at same time than >>> putting >>> the value in variable is slower than separate those actions, like: >>> a[ a.length ] = i++; >>> slower than: >>> i++; >>> a[ a.length ] = i; >>> >>> "while incremental" is faster than "for decremental". >>> This is a totaly useless information as if you can use the while >>> incremental instead of For decremental, then just use For incremental. >>> I heard that any loop was compiled to a while loop so I started coding >>> everything with a while, what is faster to write and more elegant. >>> Now I'll go back to those For loops, I promess I never stoped loving you >>> guys... >>> >>> here some convincing results : >>> takeLengthMinus : 1695 >>> takeLengthMinusOut : 1598 >>> takeLengthPlus : 1580 >>> takeLengthPlusOut : 1550 >>> >>> >>> takePushMinus : 1860 >>> takePushMinusOut : 1768 >>> takePushPlus : 1756 >>> takePushPlusOut : 1685 >>> >>> Don't compare results between separate paragraphe because they did not >>> run >>> all together: >>> >>> takeForWithLengthMinus : 1624 >>> takeForWithLengthPlus : 1581 >>> >>> The For loop is directly with operation outside, so it has to be compared >>> to the >>> >>> other outside operations: >>> >>> takeLengthMinusOut : 1686 >>> takeLengthPlusOut : 1610 >>> takePushMinusOut : 1788 >>> takePushPlusOut : 1666 >>> takeForWithLengthMinus : 1626 >>> takeForWithLengthPlus : 1563 >>> >>> I guess that's why I learned to use for( i = 0; i < n; i++ ) for my first >>> loops. >>> So if we want our code faster we have to make it longer and actually more >>> human readable, at the same time it means more computer readable as it >>> gets >>> faster....hm, is the computer so close to human...?! >>> >>> I [ mean my brain ] actually use a dicotomic way to find my current >>> client >>> folder in the list of all my works. >>> >>> cheers. >>> L >>> >>> and here the codes : >>> >>> >>> function takeLengthMinus():String{ >>> var i : int = 10000000; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i-- ){ >>> a[ a.length ] = i; >>> } >>> return "takeLengthMinus : " + ( getTimer() - t ); >>> } >>> >>> function takeLengthMinusOut():String{ >>> var i : int = 10000000; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i ){ >>> a[ a.length ] = i; >>> i--; >>> } >>> return "takeLengthMinusOut : " + ( getTimer() - t ); >>> } >>> >>> function takeLengthPlus():String{ >>> var i : int = 0; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i < 10000000 ){ >>> a[ a.length ] = i++; >>> } >>> return "takeLengthPlus : " + ( getTimer() - t ); >>> } >>> >>> function takeLengthPlusOut():String{ >>> var i : int = 0; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i < 10000000 ){ >>> a[ a.length ] = i; >>> i++; >>> } >>> return "takeLengthPlusOut : " + ( getTimer() - t ); >>> } >>> >>> function takePushMinus():String{ >>> var i : int = 10000000; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i-- ){ >>> a.push( i ); >>> } >>> return "takePushMinus : " + ( getTimer() - t ); >>> } >>> >>> function takePushMinusOut():String{ >>> var i : int = 10000000; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i ){ >>> i--; >>> a.push( i ); >>> } >>> return "takePushMinusOut : " + ( getTimer() - t ); >>> } >>> >>> function takePushPlus():String{ >>> var i : int = 0; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i < 10000000 ){ >>> a.push( i++ ); >>> } >>> return "takePushPlus : " + ( getTimer() - t ); >>> } >>> >>> function takePushPlusOut():String{ >>> var i : int = 0; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> while( i < 10000000 ){ >>> a.push( i ); >>> i++; >>> } >>> return "takePushPlusOut : " + ( getTimer() - t ); >>> } >>> >>> function takeForWithLengthMinus():String{ >>> var i : int; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> for( i = 10000000; i > 0; i-- ){ >>> a[ a.length ] = i; >>> } >>> return "takeForWithLengthMinus : " + ( getTimer() - t ); >>> } >>> >>> function takeForWithLengthPlus():String{ >>> var i : int; >>> var a: Array = new Array(); >>> var t: Number = getTimer(); >>> for( i = 0; i < 10000000; i++ ){ >>> a[ a.length ] = i; >>> } >>> return "takeForWithLengthPlus : " + ( getTimer() - t ); >>> } >>> >>> //trace( takeLengthMinus() ); >>> trace( takeLengthMinusOut() ); >>> //trace( takeLengthPlus() ); >>> trace( takeLengthPlusOut() ); >>> //trace( takePushMinus() ); >>> trace( takePushMinusOut() ); >>> //trace( takePushPlus() ); >>> trace( takePushPlusOut() ); >>> trace( takeForWithLengthMinus() ); >>> trace( takeForWithLengthPlus() ); >>> >>> _______________________________________________ >>> Flashcoders mailing list >>> Flashcoders@chattyfig.figleaf.com >>> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >>> >>> >>> >> _______________________________________________ >> Flashcoders mailing list >> Flashcoders@chattyfig.figleaf.com >> http://chattyfig.figleaf.com/mailman/listinfo/flashcoders >> >> >> __________ Information from ESET NOD32 Antivirus, version of virus >> signature database 3309 (20080730) __________ >> >> The message was checked by ESET NOD32 Antivirus. >> >> http://www.eset.com >> >> >> >> >> > > _______________________________________________ > Flashcoders mailing list > Flashcoders@chattyfig.figleaf.com > http://chattyfig.figleaf.com/mailman/listinfo/flashcoders > _______________________________________________ Flashcoders mailing list Flashcoders@chattyfig.figleaf.com http://chattyfig.figleaf.com/mailman/listinfo/flashcoders