I’ve recently been seeing more and more usage of while loops by those who I presume are interested in performance. I’ve always assumed that these was not faster than for loops, but today I am finding out.

I was taught in school that for loops are syntax sugar one small step beyond while loops. That is, these are equivalent:

for (a; b; c)
{
	d;
}
 
a;
while (b)
{
	d;
	c;
}

I learned that while studying C and C++ though and it was thoroughly supported when I learned my first assembly language and loops were indeed not native operations of the CPU. :) But these days I’m dealing with AS3, AS2, and JavaScript and things are much murkier with a VM in the way. So I devised a test to see for myself if for loops are indeed still just syntax sugar:

package
{
	import flash.display.*;
	import flash.text.*;
	import flash.utils.*;
 
	/**
	*   An app to test the speed of for loops versus while loops
	*   @author Jackson Dunstan
	*/
	public class ForVsWhile extends Sprite
	{
		public function ForVsWhile()
		{
			var logger:TextField = new TextField();
			logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(logger);
			function log(msg:*): void { logger.appendText(msg + "\n"); }
 
			var i:int;
			const NUM_ITERATIONS:int = 1000000000;
			var beforeTime:int;
 
			beforeTime = getTimer();
			for (i = 0; i < NUM_ITERATIONS; ++i) {}
			log("For (forward): " + (getTimer()-beforeTime));
 
			beforeTime = getTimer();
			for (i = NUM_ITERATIONS; i--; ) {}
			log("For (backward): " + (getTimer()-beforeTime));
 
			beforeTime = getTimer();
			i = 0;
			while (i < NUM_ITERATIONS) {++i;}
			log("While (forward): " + (getTimer()-beforeTime));
 
			beforeTime = getTimer();
			i = NUM_ITERATIONS;
			while (i--) {}
			log("While (backward): " + (getTimer()-beforeTime));
		}
	}
}

And the results are:

Environment For (forward) For (backward) While (forward) While (backward)
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP 2218 2365 2217 2365

Then I made a test for JavaScript:

/**
*   An app to test the speed of for loops versus while loops
*   @author Jackson Dunstan
*/
function log(msg) { document.write(msg + "<br/>"); }
function getTimer() { return (new Date()).getTime(); }
 
var i;
var NUM_ITERATIONS = 1000000;
var beforeTime;
 
beforeTime = getTimer();
for (i = 0; i < NUM_ITERATIONS; ++i) {}
log("For (forward): " + (getTimer()-beforeTime));
 
beforeTime = getTimer();
for (i = NUM_ITERATIONS; i--; ) {}
log("For (backward): " + (getTimer()-beforeTime));
 
beforeTime = getTimer();
i = 0;
while (i < NUM_ITERATIONS) {++i;}
log("While (forward): " + (getTimer()-beforeTime));
 
beforeTime = getTimer();
i = NUM_ITERATIONS;
while (i--) {}
log("While (backward): " + (getTimer()-beforeTime));

Note the lower number of iterations due to low browser timeout lengths. The results are:

Environment For (forward) For (backward) While (forward) While (backward)
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP, Firefox 3.5 3 2 3 2
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP, IE 8 234 94 234 94
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP, Chrome 3 8 6 8 6
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP, Safari 4 3 2 3 2

Then I made a test for AS2:

/**
*   An app to test the speed of for loops versus while loops
*   @author Jackson Dunstan
*/
class ForVsWhile
{
	function ForVsWhile()
	{
		_root.createTextField("log", 0, 0, 0, 640, 480);
		var log:Function = function(msg:String): Void { _root.log.text += msg + "\n"; }
 
		var i:Number;
		var NUM_ITERATIONS:Number = 10000000;
		var beforeTime:Number;
 
		beforeTime = getTimer();
		for (i = 0; i < NUM_ITERATIONS; ++i) {}
		log("For (forward): " + (getTimer()-beforeTime));
 
		beforeTime = getTimer();
		for (i = NUM_ITERATIONS; i--; ) {}
		log("For (backward): " + (getTimer()-beforeTime));
 
		beforeTime = getTimer();
		i = 0;
		while (i < NUM_ITERATIONS) {++i;}
		log("While (forward): " + (getTimer()-beforeTime));
 
		beforeTime = getTimer();
		i = NUM_ITERATIONS;
		while (i--) {}
		log("While (backward): " + (getTimer()-beforeTime));
	}
 
	static function main(mc:MovieClip): Void
	{
		var app:ForVsWhile = new ForVsWhile();
	}
}

Again note the lower number of iterations due to the slowness of AS2 and the old VM. The results are:

Environment For (forward) For (backward) While (forward) While (backward)
3.0 Ghz Intel Core 2 Duo, 4 GB RAM, Windows XP 1845 1832 1797 1832

As you can see from the results tables, there is usually no difference between for or while loops. The lone exception to this is AS2 where forward-iterating while loops actually outperform their for equivalents. I don’t know why this is, but given AS2’s diminishing usefulness in Flash, I don’t mind so much.

It gets more interesting when you consider both forward iteration and backward iteration. Forward iteration is faster in AS3 by a small margin, slower in JavaScript by a factor of more than two for all browsers tested, and mixed by a small margin in AS2 due to the strange forward iteration performance. Unfortunately, this harms code portability in the performance arena. When porting between these languages you may need to revisit any performance-critical areas of code and, if possible, change the directionality of their loops. Even worse, these inconsistent test results make it difficult to remember which direction to loop in various languages for maximum performance. I suppose now you at least have this page as a reference. :)

Enjoy your Thanksgiving and Black Friday festivities!