/* Read more here: http://blog.yoz.sk/2010/05/myth-buster-benchmarking-loops/ Please be patient with first click on button (and Link button), while it also generates testing list. */ package { import __AS3__.vec.Vector; import com.bit101.components.HBox; import com.bit101.components.PushButton; import flash.display.Sprite; import flash.text.TextField; import flash.utils.ByteArray; [SWF(width="465", height="465", frameRate="30", backgroundColor="#FFFFFF")] public class Benchmark extends Sprite { private static const R:uint = 1000 * 1000 * 10; //private static const R:uint = 100000; private static const LOOP_TYPE:Array = ['For', 'Foreach', 'While']; private static const VARIABLE_TYPE:Array = ['Uint', 'Int', 'Number']; private static const INCREMENT_TYPE:Array = ['Pre', 'Post']; private static const COURSE_TYPE:Array = ['Increment', 'Decrement']; private var logTextField:TextField = new TextField(); private var firstLink:Linked; private var modelArray:Vector.<uint>; private var modelBytes:ByteArray; private var testFastest:uint = uint.MAX_VALUE; private var globalFastest:uint = uint.MAX_VALUE; public function Benchmark() { logTextField.y = 20; logTextField.width = stage.stageWidth; logTextField.height = stage.stageHeight - logTextField.y; addChild(logTextField); var box:HBox = new HBox(this); box.spacing = 0; new PushButton(box, 0, 0, "For", testFor).width = 39; new PushButton(box, 0, 0, "Foreach", testForeach).width = 39; new PushButton(box, 0, 0, "While", testWhile).width = 39; new PushButton(box, 0, 0, "Uint", testUint).width = 39; new PushButton(box, 0, 0, "Int", testInt).width = 39; new PushButton(box, 0, 0, "Number", testNumber).width = 39; new PushButton(box, 0, 0, "Pre", testPre).width = 39; new PushButton(box, 0, 0, "Post", testPost).width = 39; new PushButton(box, 0, 0, "Increment", testIncrement).width = 39; new PushButton(box, 0, 0, "Decrement", testDecrement).width = 39; new PushButton(box, 0, 0, "Link", testLink).width = 39; new PushButton(box, 0, 0, "Bytes", testBytes).width = 39; } private function generateArray():void { if(modelArray) return; log("----- Generating array -----"); modelArray = new Vector.<uint>(); for(var i:uint = 0; i < R; i++) modelArray.push(1); } private function generateLink():void { if(firstLink) return; log("----- Generating linked list -----"); firstLink = new Linked(); var link:Linked = firstLink; for(var j:uint = 1; j < R; j++) { link.next = new Linked(); link = link.next; } } private function generateBytes():void { if(modelBytes) return; modelBytes = new ByteArray(); for(var j:uint = 0; j < R; j++) modelBytes.writeInt(1); } private function testFor(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting For test --- (" + R +" iterations)"); for each(var vt:String in VARIABLE_TYPE) for each(var it:String in INCREMENT_TYPE) for each(var ct:String in COURSE_TYPE) measure("testFor" + vt + it + ct); log(""); } private function testForeach(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Foreach test --- (" + R +" iterations)") for each(var vt:String in VARIABLE_TYPE) measure("testForeach" + vt); log(""); } private function testWhile(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting While test --- (" + R +" iterations)") for each(var vt:String in VARIABLE_TYPE) for each(var it:String in INCREMENT_TYPE) for each(var ct:String in COURSE_TYPE) measure("testWhile" + vt + it + ct); log(""); } private function testUint(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Uint test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var it:String in INCREMENT_TYPE) for each(var ct:String in COURSE_TYPE) measure("test" + lt + "Uint" + it + ct); log(""); } private function testInt(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Int test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var it:String in INCREMENT_TYPE) for each(var ct:String in COURSE_TYPE) measure("test" + lt + "Int" + it + ct); log(""); } private function testNumber(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Number test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var it:String in INCREMENT_TYPE) for each(var ct:String in COURSE_TYPE) measure("test" + lt + "Number" + it + ct); log(""); } private function testPre(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Pre test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var vt:String in VARIABLE_TYPE) for each(var ct:String in COURSE_TYPE) measure("test" + lt + vt + "Pre" + ct); log(""); } private function testPost(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Post test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var vt:String in VARIABLE_TYPE) for each(var ct:String in COURSE_TYPE) measure("test" + lt + vt + "Post" + ct); log(""); } private function testIncrement(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Increment test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var vt:String in VARIABLE_TYPE) for each(var it:String in INCREMENT_TYPE) measure("test" + lt + vt + it + "Increment"); log(""); } private function testDecrement(... rest):void { generateArray(); testFastest = uint.MAX_VALUE; log("--- Starting Decrement test --- (" + R +" iterations)") for each(var lt:String in LOOP_TYPE) for each(var vt:String in VARIABLE_TYPE) for each(var it:String in INCREMENT_TYPE) measure("test" + lt + vt + it + "Decrement"); log(""); } private function testLink(... rest):void { generateLink(); testFastest = uint.MAX_VALUE; log("--- Starting Decrement test --- (" + R +" iterations)") measure("testLinked"); log(""); } private function testBytes(... rest):void { generateBytes(); testFastest = uint.MAX_VALUE; log("--- Starting Bytes test --- (" + R +" iterations)") measure("testByteArrayRead"); measure("testByteArrayFor"); log(""); } private function log(message:String):void { logTextField.appendText(message + "\n"); logTextField.scrollV = logTextField.maxScrollV; } private function measure(methodName:String):void { if(!this.hasOwnProperty(methodName)) return; var method:Function = this[methodName]; var t0:Date = new Date(); method(); var t:uint = new Date().time - t0.time; var flag:String = ""; if(t <= globalFastest) { flag = "*GLOBAL FASTEST*"; globalFastest = testFastest = t; } else if(t <= testFastest) { flag = "*TEST FASTEST*"; testFastest = t; } log(methodName + ": " + t + " ms. " + flag); } public function testForUintPostIncrement():void { for(var i:uint = 0; i < R; i++) modelArray[i]; } public function testForUintPostDecrement():void { for(var i:uint = R - 1; i; i--) modelArray[i]; modelArray[i]; } public function testForIntPostIncrement():void { for(var i:int = 0; i < R; i++) modelArray[i]; } public function testForIntPostDecrement():void { for(var i:int = R - 1; i > -1; i--) modelArray[i]; } public function testForNumberPostIncrement():void { for(var i:Number = 0; i < R; i++) modelArray[i]; } public function testForNumberPostDecrement():void { for(var i:Number = R - 1; i > -1; i--) modelArray[i]; } public function testForUintPreIncrement():void { for(var i:uint = 0; i < R; ++i) modelArray[i]; } public function testForUintPreDecrement():void { for(var i:uint = R - 1; i; --i) modelArray[i]; modelArray[i]; } public function testForIntPreIncrement():void { for(var i:int = 0; i < R; ++i) modelArray[i]; } public function testForIntPreDecrement():void { for(var i:int = R - 1; i > -1; --i) modelArray[i]; } public function testForNumberPreIncrement():void { for(var i:Number = 0; i < R; ++i) modelArray[i]; } public function testForNumberPreDecrement():void { for(var i:Number = R - 1; i > -1; --i) modelArray[i]; } public function testForeachUint():void { for each(var i:uint in modelArray) i; } public function testForeachInt():void { for each(var i:int in modelArray) i; } public function testForeachNumber():void { for each(var i:Number in modelArray) i; } public function testWhileUintPreDecrement():void { var i:uint = modelArray.length; while(--i) modelArray[i]; modelArray[i]; } public function testWhileUintPostDecrement():void { var i:uint = modelArray.length; while(i--) modelArray[i]; } public function testWhileIntPreDecrement():void { var i:int = modelArray.length; while(--i > -1) modelArray[i]; } public function testWhileIntPostDecrement():void { var i:int = modelArray.length; while(i--) modelArray[i]; } public function testWhileNumberPreDecrement():void { var i:Number = modelArray.length; while(--i > -1) modelArray[i]; } public function testWhileNumberPostDecrement():void { var i:Number = modelArray.length; while(i--) modelArray[i]; } public function testWhileUintPostIncrement():void { var i:uint = 0, l:uint = modelArray.length; while(i < l) modelArray[i++]; } public function testWhileUintPreIncrement():void { var i:uint = 0, l:uint = modelArray.length; modelArray[i]; while(++i < l) modelArray[i]; } public function testWhileIntPostIncrement():void { var i:int = 0, l:int = modelArray.length; while(i < l) modelArray[i++]; } public function testWhileIntPreIncrement():void { var i:int = -1, l:int = modelArray.length; while(++i < l) modelArray[i]; } public function testWhileNumberPostIncrement():void { var i:Number = 0, l:Number = modelArray.length; while(i < l) modelArray[i++]; } public function testWhileNumberPreIncrement():void { var i:Number = -1, l:Number = modelArray.length; while(++i < l) modelArray[i]; } public function testLinked():void { var link:Linked = firstLink; while(link) link = link.next; } public function testByteArrayRead():void { var i:uint; modelBytes.position = 0; while(true) { try { i = modelBytes.readInt(); } catch(error:Error) { break; } } } public function testByteArrayFor():void { for(var i:int = R - 1; i > -1; i--) modelBytes[i]; } } } class Linked extends Object { public var next:Linked; public function Linked():void { super(); } } Loop Benchmark Test 2