PD: I have made some tests and it seems like using nested loops is much more faster than using modulo + floor or modulo + int cast.
The results shows that while the elapsed time in nested loops tends to grow linearly, when using modulo tends to grow exponentially. It shouldn't be a problem with a small number of rows/cols, though. The results: 100 rows x 100 cols rowFloor:2 rowIntCast:1 rowNestedLoops:0 500 rows x 500 cols rowFloor:78 rowIntCast:27 rowNestedLoops:1 1000 rows x 1000 cols rowFloor:287 rowIntCast:96 rowNestedLoops:4 2500 rows x 2500 cols rowFloor:1822 rowIntCast:608 rowNestedLoops:18 The tested code: package { import flash.utils.getTimer; public class Rowing { private var rows:int = 500; private var cols:int = 500; public function Rowing() { } public function rowFloor():int { var init:int = getTimer(); var len:int = rows * cols; var i:int = 0; var r:int = 0; var c:int = 0; for (i=0; i < len; i++) { c = i % cols; r = Math.floor(i/cols); // trace("c:"+c+"|r:"+r); } return getTimer() - init; } public function rowIntCast():int { var init:int = getTimer(); var len:int = rows * cols; var i:int = 0; var r:int = 0; var c:int = 0; for (i=0; i < len; i++) { c = i % cols; r = int(i/cols); // trace("c:"+c+"|r:"+r); } return getTimer() - init; } public function rowNestedLoops():int { var init:int = getTimer(); var r:int = 0; var c:int = 0; for(r = 0; r < rows; r++) { for(c = 0; c < cols; c++) { // trace("c:"+c+"|r:"+r); } } return getTimer() - init; } } } Cheers Juan Pablo Califano 2008/5/25, Juan Pablo Califano <[EMAIL PROTECTED]>: > > I probably would, if it just were a superb compiler instead of a > nice language (but incompatible at source level with AS) and a superb > compiler ;) > > And if I were writting performance-critical suff (which I'm not), I'd > certainly consider using it for building external swf libraries. > > Cheers > Juan Pablo Califano > > > > 2008/5/25, laurent <[EMAIL PROTECTED]>: >> >> Yes. And you can jump to Haxe ;) >> >> cheers >> L >> >> Juan Pablo Califano a écrit : >> >>> Thanks for the link. >>> >>> It seems clear from the tests that Math.floor *is* slower than casting. >>> It >>> think the implementation posted in the blog has a bug, though. The result >>> of >>> casting to int is the same as using Math.floor as long as the int is >>> positive. But, if the int is negative, the results will be different. >>> >>> function testFloor():void { >>> var num:Number = -1.5; >>> var res:int = Math.floor(num); >>> trace("testFloor:"+res); // traces -2 >>> } >>> function testCast():void { >>> var num:Number = -1.5; >>> var res:int = int(num); >>> trace("testCast:"+res); // traces -1 >>> } >>> >>> Maybe that's the reason why the compiler doesn't replace a call to >>> Math.floor with a simple cast... >>> >>> Anyway, my point is that there are many layers under the actionscript >>> code >>> and the compiler could be making some optimizations you're normally not >>> aware of. I've checked compiling and the decompiling the above functions >>> to >>> the assembly "il" representation (with abcdump). No such optimizations >>> are >>> made, so you're right about this. >>> >>> Nevertheless, I think some optimizations could be done (and maybe will >>> be, >>> some day?) on the compiler, like, for instance, inlining calls to >>> Math.floor >>> with code that would look like this, if it were Actionscript: >>> >>> Math.floor(num); >>> >>> --> >>> >>> num > 0 ? int(num) : int(num) - 1; >>> >>> >>> Cheers >>> Juan Pablo Califano >>> >>> >>> >>> >>> 2008/5/25, laurent <[EMAIL PROTECTED]>: >>> >>> >>>> John Grden wrote a post about many Math optimisations in AS3, you can >>>> find >>>> the code to test at home here: >>>> >>>> http://www.rockonflash.com/blog/?p=63 >>>> >>>> L >>>> >>>> Juan Pablo Califano a écrit : >>>> >>>> >>>> >>>>> I use modulo for rowing too and int() instead of Math.floor() as it's >>>>> >>>>> >>>>>> faster. ;) >>>>>> >>>>>> >>>>>> >>>>>> >>>>> Laurent, >>>>> >>>>> is it, really? >>>>> >>>>> I'm not sure. I recently made similar assumptions about what's faster >>>>> an >>>>> what's slower based on what "made sense", only to be proved wrong by >>>>> some >>>>> actual benchmarking. >>>>> >>>>> Anyway, if the variable is typed as an int, my understanding is that >>>>> you >>>>> don't need to use Math.floor or a cast to int, since the decimal part >>>>> will >>>>> be truncated automatically. >>>>> >>>>> Another option to discard decimals is to use bit shifting ( i >> 0), >>>>> which >>>>> some people say it's faster. But in the end, how do you know that under >>>>> the >>>>> hood, the flash player is not doing exactly the same operation for an >>>>> int >>>>> cast, a Math.floor call and a shift zero ? >>>>> >>>>> Cheers >>>>> Juan Pablo Califano >>>>> >>>>> >>>>> 2008/5/25, laurent <[EMAIL PROTECTED]>: >>>>> >>>>> >>>>> >>>>> >>>>>> Thanks Jesse for the neat explanation, it all make sense, that's a >>>>>> clever >>>>>> trick to get a smooth movement of this type where tweening is not a >>>>>> solution. >>>>>> That can be applied to other things just to get the right value to >>>>>> change. >>>>>> Very good to know that enter Frame and Timer are approximations. >>>>>> I use modulo for rowing too and int() instead of Math.floor() as it's >>>>>> faster. ;) >>>>>> >>>>>> L >>>>>> >>>>>> Jesse Graupmann a écrit : >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>>> @Laurent >>>>>>> >>>>>>> So modulus is great and slow from what I've read. I tend to use it in >>>>>>> row/ >>>>>>> column calculation rather than wrapping a MovieClip position. >>>>>>> >>>>>>> var num:int = 6; >>>>>>> var cols:int = 3; >>>>>>> >>>>>>> for ( var i:int = 0; i < num; i++ ) { >>>>>>> var row:int = Math.floor( i / cols ); >>>>>>> var col:int = i % cols; >>>>>>> >>>>>>> trace ( "i: " + i + "\trow:" + row + "\tcol:" + col ); >>>>>>> } >>>>>>> >>>>>>> i: 0 row:0 col:0 >>>>>>> i: 1 row:0 col:1 >>>>>>> i: 2 row:0 col:2 >>>>>>> i: 3 row:1 col:0 >>>>>>> i: 4 row:1 col:1 >>>>>>> i: 5 row:1 col:2 >>>>>>> >>>>>>> >>>>>>> In the previous post I'm moving a MovieClip to the right X.X pixels >>>>>>> and >>>>>>> when >>>>>>> its position is off the screen I reset it back to 0. If I used the >>>>>>> modulus >>>>>>> method, the movement would always be rounded numbers and appear >>>>>>> jerkier >>>>>>> than >>>>>>> this experiment requires. I'm actually hoping to round to the nearest >>>>>>> twip. >>>>>>> >>>>>>> >>>>>>> As for the examples themselves.... >>>>>>> >>>>>>> >>>>>>> #1 >>>>>>> onT is a timer tick. So about every 30ms it will move the MovieClip X >>>>>>> pixels >>>>>>> based on speed. Because Timers are never accurate to what you expect >>>>>>> ( >>>>>>> they >>>>>>> only get as close as they can - see below ) onT will always be >>>>>>> dragging >>>>>>> behind the other two methods and moving at varied speeds. >>>>>>> >>>>>>> // Elapsed time from a tick on var t:Timer = new Timer(30); >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> 47,38,36,36,36,36,36,38,36,35,35,36,36,34,36,42,36,35,35,36,35,37,40,36,36,3 >>>>>>> >>>>>>> >>>>>>> >>>>>>> 6,36,36,54,36,37,35,34,36,38,38,36,36,36,36,69,39,35,36,35,36,36,42,44,36,36 >>>>>>> >>>>>>> >>>>>>> >>>>>>> ,35,36,35,63,37,33,36,35,37,40,30,35,34,36,92,55,66,35,36,34,36,46,36,36,36, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 36,97,50,34,35,35,36,36,34,33,218,142,49,121,59,110,84,102,65,106,66,58,55,6 >>>>>>> >>>>>>> >>>>>>> >>>>>>> 5,34,36,35,36,64,33,35,36,35,37,31,48,34,36,35,35,36,77,34,34,36,36,36,70,36 >>>>>>> >>>>>>> >>>>>>> >>>>>>> ,35,37,35,37,74,54,35,36,71,65,35,36,36,35,35,73,37,36,36,34,43,66,35,38,36, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 35,34,73,36,34,50,59,67,37,36,36,36,56,47,37,36,36,34,36,30,46,35,36,36,36,5 >>>>>>> >>>>>>> >>>>>>> >>>>>>> 9,46,35,36,36,36,59,45,35,36,36,34,36,32,48,37,37,35,38,56,48,34,36,36,36,58 >>>>>>> >>>>>>> >>>>>>> >>>>>>> ,47,34,37,36,36,57,72,45,36,50,55,45,35,35,35,36,61,45,36,35,35,36,66,45,131 >>>>>>> >>>>>>> ,39,45,33,37,34,37,34,45,51,36,51,49,38,67,35,36,36,34,43,47,38,50,35,34 >>>>>>> >>>>>>> // Difference from expected 30ms >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> 17,8,6,6,6,6,6,8,6,5,5,6,6,4,6,12,6,5,5,6,5,7,10,6,6,6,6,6,24,6,7,5,4,6,8,8, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 6,6,6,6,39,9,5,6,5,6,6,12,14,6,6,5,6,5,33,7,3,6,5,7,10,0,5,4,6,62,25,36,5,6, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 4,6,16,6,6,6,6,67,20,4,5,5,6,6,4,3,188,112,19,91,29,80,54,72,35,76,36,28,25, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 35,4,6,5,6,34,3,5,6,5,7,1,18,4,6,5,5,6,47,4,4,6,6,6,40,6,5,7,5,7,44,24,5,6,4 >>>>>>> >>>>>>> >>>>>>> >>>>>>> 1,35,5,6,6,5,5,43,7,6,6,4,13,36,5,8,6,5,4,43,6,4,20,29,37,7,6,6,6,26,17,7,6, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 6,4,6,0,16,5,6,6,6,29,16,5,6,6,6,29,15,5,6,6,4,6,2,18,7,7,5,8,26,18,4,6,6,6, >>>>>>> >>>>>>> >>>>>>> >>>>>>> 28,17,4,7,6,6,27,42,15,6,20,25,15,5,5,5,6,31,15,6,5,5,6,36,15,101,9,15,3,7,4 >>>>>>> ,7,4,15,21,6,21,19,8,37,5,6,6,4,13,17,8,20,5,4 >>>>>>> >>>>>>> >>>>>>> #2 >>>>>>> onT2 - To compensate for the difference, I decide that for every 30ms >>>>>>> that >>>>>>> have passed the MovieClip should increment the correct amount ( 1 >>>>>>> pixel >>>>>>> ). >>>>>>> When the tick occurs, I subtract the stored time (lastTick2) from the >>>>>>> current time giving me the most accurate elapsed time. Dividing by >>>>>>> the >>>>>>> tick >>>>>>> time gives me a percentage of my expected elapsed time. Multiplying >>>>>>> that >>>>>>> value by the speed produces the most accurate change over time. >>>>>>> >>>>>>> #3 >>>>>>> onT3 - Because I can assume speed based on elapsed time is the most >>>>>>> accurate, it won't matter when I call the function as long as it >>>>>>> happens >>>>>>> once per frame. So onT3 just uses the ENTER_FRAME event to calculate >>>>>>> speed >>>>>>> based on elapsed time using lastTick3. >>>>>>> >>>>>>> Here is another example that is commented a bit better and should >>>>>>> make >>>>>>> all >>>>>>> this very apparent. >>>>>>> >>>>>>> stage.align = "TL"; >>>>>>> stage.scaleMode = "noScale"; >>>>>>> stage.addEventListener ( Event.ENTER_FRAME, onFrame ); >>>>>>> >>>>>>> // for every (stepTime)ms move (stepRate)pixels >>>>>>> var stepTime:int = 30; var stepRate:int = 1; >>>>>>> var time:int = getTimer(); >>>>>>> >>>>>>> function onFrame ( e:Event ):void { >>>>>>> // time since last frame >>>>>>> var elapsedTime:int = getTimer() - time; >>>>>>> >>>>>>> // store current time for the next check >>>>>>> time = getTimer(); >>>>>>> >>>>>>> // percentage of expected time >>>>>>> var timePercentage:Number = elapsedTime / stepTime; >>>>>>> >>>>>>> // rate compensation >>>>>>> var movement:Number = timePercentage * stepRate; >>>>>>> >>>>>>> // move mc >>>>>>> mc.x += movement; >>>>>>> >>>>>>> // wrap if off the stage >>>>>>> if ( mc.x > stage.stageWidth ) mc.x = 0; >>>>>>> } >>>>>>> >>>>>>> >>>>>>> Hasta! >>>>>>> Jesse >>>>>>> >>>>>>> >>>>>>> -----Original Message----- >>>>>>> From: [EMAIL PROTECTED] >>>>>>> [mailto:[EMAIL PROTECTED] On Behalf Of >>>>>>> laurent >>>>>>> Sent: Saturday, May 24, 2008 2:13 AM >>>>>>> To: Flash Coders List >>>>>>> Subject: Re: [Flashcoders] Tweening text more smoothly - AS3 >>>>>>> >>>>>>> >>>>>>> :) I just read about wraping using modulus on Grant Skinner's blog: >>>>>>> >>>>>>> sprite.x = (sprite.x + 5) % stage.stageWidth; >>>>>>> >>>>>>> And then get where was that checkWrap methods :] >>>>>>> Still I'm interested in the onT methods...I don't think I will get >>>>>>> them >>>>>>> before Grant's next post. >>>>>>> >>>>>>> the article about using modulus: >>>>>>> http://www.gskinner.com/blog/archives/2008/05/core_as3_modulu.html >>>>>>> >>>>>>> L >>>>>>> >>>>>>> Jesse Graupmann a écrit : >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> Maybe converting the actual time elapsed to a constant rate of >>>>>>>> motion >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> could >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> help... who knows? >>>>>>>> >>>>>>>> >>>>>>>> stage.align = "TL"; >>>>>>>> stage.scaleMode = "noScale"; >>>>>>>> >>>>>>>> function checkWrap ( o:DisplayObject ):void >>>>>>>> { >>>>>>>> if ( o.x > stage.stageWidth ) o.x = 0; >>>>>>>> } >>>>>>>> >>>>>>>> var speed:Number = 1; >>>>>>>> var tick:Number = 30; >>>>>>>> var lastTick2:Number = getTimer(); >>>>>>>> var lastTick3:Number = getTimer(); >>>>>>>> var t:Timer = new Timer(tick); >>>>>>>> var t2:Timer = new Timer(tick); >>>>>>>> >>>>>>>> t.addEventListener( TimerEvent.TIMER, onT ); >>>>>>>> t2.addEventListener( TimerEvent.TIMER, onT2 ); >>>>>>>> stage.addEventListener( Event.ENTER_FRAME, onT3 ); >>>>>>>> t.start(); >>>>>>>> t2.start(); >>>>>>>> >>>>>>>> >>>>>>>> function onT( e:TimerEvent ):void >>>>>>>> { >>>>>>>> // timer >>>>>>>> mc.x += speed; >>>>>>>> checkWrap ( mc ); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> function onT2( e:TimerEvent ):void >>>>>>>> { >>>>>>>> // timer + speed >>>>>>>> mc2.x += (( getTimer() - lastTick2 ) / tick ) * speed; >>>>>>>> lastTick2 = getTimer(); >>>>>>>> checkWrap ( mc2 ); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> function onT3( e:Event ):void >>>>>>>> { >>>>>>>> // enter frame + speed >>>>>>>> mc3.x += (( getTimer() - lastTick3 ) / tick ) * speed; >>>>>>>> lastTick3 = getTimer(); >>>>>>>> checkWrap ( mc3 ); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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 >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> _______________________________________________ >>>>> 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 >>>> >>>> >>>> >>> _______________________________________________ >>> 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 >> > > _______________________________________________ Flashcoders mailing list Flashcoders@chattyfig.figleaf.com http://chattyfig.figleaf.com/mailman/listinfo/flashcoders