Today’s article is a followup to a flawed article I wrote last October. Skyboy’s comment brought this to my attention, so today I’m (hopefully) correcting the problems with an important test: AS3 operators. Read on for the updated test code and results.

The first problem pointed out is that the anonymous log function caused an activation object to be generated by the compiler, which in turn caused a slowdown. Coincidentally, the original article was written one week before I wrote Activation Objects, detailing the slowdown. From then on, I stopped using local log functions. The updated test removes the local log function.

Secondly, the test for <= had a typo causing it to actually test for the < operator. The updated test fixes this typo. Also, the original test had no declared test for <. These test was added.

Thirdly, the original test only tested post-increment (e.g. val++) and vaguely labeled the tests. The new test explicitly checks the performance of pre- and post-increment.

Fourthly, with such cheap operators, the loop’s time itself was distorting the results. The updated test does two things to address this. First, the loop time is subtracted from the total time. Since this frequently yields negative values, the test is run every frame until all results are non-negative.

Lastly, when comparing results, even with loop times removed, there was much statistical variance between them. To correct for this, the test is run every frame until five successful (i.e. all values are non-negative) tests are generated. The results are then averaged.

Now for the test. Just as a warning, it is extremely long as it tests a lot of operators. The results table follows the source code, so feel free to scroll on past the test. Also, if you decide to compile and run the test, keep in mind that it will take quite a while to complete due to a combination of a high repetition count for each operator, the requirement of all non-negative values, and the requirement of multiple successful tests.

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
	import flash.text.*;
 
	/**
	*   An app to test operator performance
	*   @author Jackson Dunstan
	*/
	[SWF(frameRate="1000")]
	public class OperatorPerformance extends Sprite
	{
		private static const SUCCESSES:int = 5;
		private var __logger:TextField = new TextField();
		private var __results:Array;
		private var __resultsCol:int;
		private var __resultsRow:int;
		private var __totalResults:Array;
		private var __successes:int;
		private var __numResultRows:int;
		private var __numResultCols:int;
 
		public function OperatorPerformance()
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			__logger.autoSize = TextFieldAutoSize.LEFT;
			__logger.defaultTextFormat = new TextFormat("_typewriter", 13);
			__logger.text = "Progress: " + __successes + "/" + SUCCESSES;
			addChild(__logger);
 
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
 
		private function initResultsTable(): void
		{
			__results = [
				["Operator","int","uint","int/uint","Number","int/Number","uint/Number"],
				["&","","","","","",""],
				["|","","","","","",""],
				["^","","","","","",""],
				["~","","","","","",""],
				[">>","","","","","",""],
				[">>>","","","","","",""],
				["<<","","","","","",""],
				["+","","","","","",""],
				["-","","","","","",""],
				["*","","","","","",""],
				["/","","","","","",""],
				["%","","","","","",""],
				["v++","","","","","",""],
				["v--","","","","","",""],
				["++v","","","","","",""],
				["--v","","","","","",""],
				["==","","","","","",""],
				["===","","","","","",""],
				["!=","","","","","",""],
				["!==","","","","","",""],
				[">","","","","","",""],
				["<","","","","","",""],
				[">=","","","","","",""],
				["<=","","","","","",""],
				["&&","","","","","",""],
				["||","","","","","",""],
				["!","","","","","",""],
				["=","","","","","",""]
			];
			__numResultRows = __results.length;
			__numResultCols = __results[0].length;
			if (__totalResults == null)
			{
				__totalResults = __results.slice();
				for (var i:int = 0; i < __totalResults.length; ++i)
				{
					__totalResults[i] = __totalResults[i].slice();
				}
			}
			__resultsCol = 1;
			__resultsRow = 1;
		}
 
		private function reportResult(result:String): Boolean
		{
			__results[__resultsRow++][__resultsCol] = result;
			return result == "n/a" || int(result) >= 0;
		}
 
		public function onEnterFrame(ev:Event): void
		{
			var i:int;
			const REPS:int = 10000000;
			var beforeTime:int;
			var afterTime:int;
			var loopTime:int;
			var val1int:int;
			var val2int:int;
			var val1uint:uint;
			var val2uint:uint;
			var val1number:Number;
			var val2number:Number;
			initResultsTable();
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
			}
			afterTime = getTimer();
			loopTime = afterTime - beforeTime;
 
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int & val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int | val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int ^ val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				~val1int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >> val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >>> val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int << val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int + val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int - val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int * val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int / val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int % val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int++;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int--;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				++val1int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				--val1int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int == val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int === val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int != val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int !== val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int > val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int < val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >= val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int <= val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int && val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int || val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				!val1int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int = val2int;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			__resultsCol++;
			__resultsRow = 1;
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint & val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint | val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint ^ val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				~val1uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >> val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >>> val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint << val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint + val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint - val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint * val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint / val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint % val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint++;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint--;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				++val1uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				--val1uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint == val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint === val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint != val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint !== val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint > val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint < val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >= val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint <= val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint && val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint || val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				!val1uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint = val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			__resultsCol++;
			__resultsRow = 1;
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int & val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int | val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int ^ val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >> val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >>> val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int << val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int + val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int - val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int * val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int / val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int % val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int == val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int === val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int != val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int !== val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int > val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int < val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >= val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int <= val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int && val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int || val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int = val2uint;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			__resultsCol++;
			__resultsRow = 1;
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number & val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number | val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number ^ val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				~val1number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number >> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number >>> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number << val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number + val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number - val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number * val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number / val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number % val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number++;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number--;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				++val1number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				--val1number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number == val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number === val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number != val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number !== val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number > val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number < val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number >= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number <= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number && val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number || val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				!val1number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1number = val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			__resultsCol++;
			__resultsRow = 1;
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int & val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int | val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int ^ val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >>> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int << val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int + val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int - val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int * val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int / val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int % val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int == val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int === val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int != val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int !== val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int > val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int < val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int >= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int <= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int && val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int || val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1int = val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			__resultsCol++;
			__resultsRow = 1;
			val1int = 1;
			val2int = 2;
			val1uint = 1;
			val2uint = 2;
			val1number = 1;
			val2number = 2;
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint & val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint | val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint ^ val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >>> val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint << val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint + val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint - val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint * val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint / val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint % val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint == val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint === val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint != val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint !== val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint > val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint < val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint >= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint <= val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint && val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint || val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			if (!reportResult("n/a")) { return; }
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				val1uint = val2number;
			}
			afterTime = getTimer();
			if (!reportResult(String(afterTime-beforeTime-loopTime))) { return; }
 
			for (var row:int = 1; row < __numResultRows; ++row)
			{
				for (var col:int = 1; col < __numResultCols; ++col)
				{
					var cell:String = __results[row][col];
					if (cell != "n/a")
					{
						var totalCell:String = __totalResults[row][col];
						__totalResults[row][col] = int(cell) + int(totalCell);
					}
				}
			}
			__successes++;
			if (__successes == SUCCESSES)
			{
				for (row = 1; row < __numResultRows; ++row)
				{
					for (col = 1; col < __numResultCols; ++col)
					{
						cell = __totalResults[row][col];
						if (cell != "n/a")
						{
							__totalResults[row][col] = Number(cell) / SUCCESSES;
						}
					}
				}
				__logger.text = __totalResults.join("\n");
				removeEventListener(Event.ENTER_FRAME, onEnterFrame);
			}
			else
			{
				__logger.text = "Progress: " + __successes + "/" + SUCCESSES;
			}
		}
	}
}

Here is the test environment I ran the above app on:

  • Flex SDK (MXMLC) 4.1.0.16076, compiling in release mode (no debugging or verbose stack traces)
  • Release version of Flash Player 10.2.152.26
  • 2.4 Ghz Intel Core i5
  • Mac OS X 10.6.6
Operator int uint int/uint Number int/Number uint/Number
& 2.2 2 3 2.2 3.4 2.6
| 3.6 4 2.4 2.2 2.8 4.2
^ 2.4 3 2.6 2.2 3.4 2.6
~ 3.6 3 0 2 0 0
>> 4.6 2.2 4.4 2 5 2.4
>>> 4 4.8 2.6 1.6 4 3.8
<< 3 2.8 4 2.6 1.8 2.6
+ 3.6 3.8 2.6 1.6 4.6 4
3.4 2.2 4.2 3.2 2.6 3
* 4 4.2 2.8 1.4 4.6 4.4
/ 3 2.8 3.6 2.6 2.6 2.2
% 4 3.8 3.8 4.4 4.6 4
v++ 1.4 1.2 0 16.2 0 0
v-- 1.4 1.6 0 16.2 0 0
++v 1.2 2 0 16.2 0 0
--v 1.6 1.4 0 15.8 0 0
== 4.6 3.8 4.6 4 3 3
=== 2.8 1.4 2.2 2.6 3.6 2
!= 3.2 4.2 3.2 3.8 2.4 3.2
!== 2.4 4.2 2.4 1.8 4 1.6
> 4.2 3.6 3 4.4 2.8 2.6
< 3.2 2 2.6 2.2 3.8 2.4
>= 4 4.6 2.6 4 3.8 2.2
<= 2.6 3 4.8 3.6 4.6 2.8
&& 1.4 2 73.6 25.2 71.2 70
|| 2.4 1.6 71.2 25.6 73.8 73.4
! 2.4 2.4 0 2.6 0 0
= 4 3.6 4.4 4 1.8 2.4

At this point I should mention that it is very tempting to look at these numbers and leap to conclusions. It looks like the >> operator is more than twice as fast with Number than with int. This is not true due to the margin of error, even with the added averaging in this version of the test.

So, the way I recommend reading the above numbers is to group similar values together. I’ve binned them in groups of five below:

Operator int uint int/uint Number int/Number uint/Number
& 0-5 0-5 0-5 0-5 0-5 0-5
| 0-5 0-5 0-5 0-5 0-5 0-5
^ 0-5 0-5 0-5 0-5 0-5 0-5
~ 0-5 0-5 0-5 0-5 0-5 0-5
>> 0-5 0-5 0-5 0-5 0-5 0-5
>>> 0-5 0-5 0-5 0-5 0-5 0-5
<< 0-5 0-5 0-5 0-5 0-5 0-5
+ 0-5 0-5 0-5 0-5 0-5 0-5
0-5 0-5 0-5 0-5 0-5 0-5
* 0-5 0-5 0-5 0-5 0-5 0-5
/ 0-5 0-5 0-5 0-5 0-5 0-5
% 0-5 0-5 0-5 0-5 0-5 0-5
v++ 0-5 0-5 0-5 15-20 0-5 0-5
v-- 0-5 0-5 0-5 15-20 0-5 0-5
++v 0-5 0-5 0-5 15-20 0-5 0-5
--v 0-5 0-5 0-5 15-20 0-5 0-5
== 0-5 0-5 0-5 0-5 0-5 0-5
=== 0-5 0-5 0-5 0-5 0-5 0-5
!= 0-5 0-5 0-5 0-5 0-5 0-5
!== 0-5 0-5 0-5 0-5 0-5 0-5
> 0-5 0-5 0-5 0-5 0-5 0-5
< 0-5 0-5 0-5 0-5 0-5 0-5
>= 0-5 0-5 0-5 0-5 0-5 0-5
<= 0-5 0-5 0-5 0-5 0-5 0-5
&& 0-5 0-5 70-75 25-30 70-75 70-75
|| 0-5 0-5 70-75 25-30 70-75 70-75
! 0-5 0-5 0-5 0-5 0-5 0-5
= 0-5 0-5 0-5 0-5 0-5 0-5

Notice that almost all of the operators—those in the 0-5 range—are extremely fast. What I recommend concerning yourself with are those that aren’t in the 0-5 range. Namely, these:

  • Number-- (3-4x slower)
  • Number++ (3-4x slower)
  • -Number (3-4x slower)
  • ++Number (3-4x slower)
  • int && uint (14-15x slower)
  • int || uint (14-15x slower)
  • Number && Number (5-6x slower)
  • Number || Number (5-6x slower)
  • int && uint (14-15x slower)
  • int && Number (14-15x slower)
  • int || Number (14-15x slower)
  • uint && Number (14-15x slower)
  • uint || Number (14-15x slower)

The above list should serve as a good reference when you’re questioning the contents of a very hot loop.

Thanks again to Skyboy for pointing out some of the flaws in the original test. Please, as always, feel free to comment if you too find anything wrong with any of tests or just to chime in with your thoughts.