残念な話。 ―配列への循環アクセス 2―

昨日のエントリ( 感嘆した話。 ―配列への循環アクセス― )について、早速テストしてみました。
短い配列を循環しながら、長い配列にコピーしていくという処理で計ってみます。
今回も、JavaScriptで書きます。

まず、時間を計る関数を準備。

関数functionObjectを、functionCount回実行して、かかった時間(ms)の平均を返します。

function getTheFuncTime(functionObject, functionCount) {	// :Number
	var start, end;
	functionCount = functionCount || 1;
	start = new Date();
	for(var i=0; i<functionCount; i++) {
		functionObject();
	}
	end = new Date();
	return (end - start) / functionCount;
}

コピー元、コピー先の配列を準備。

var sourceArray = [];
var sourceArrayLength = 10;

var destinationArray = [];
var destinationArrayLength = 100000;

for (var i=0; i<sourceArrayLength; i++) {
	sourceArray.push(Math.random());
}

if文方式で循環する関数test01。

function test01() {		// :void
	var currentIndex = 0;
	for (var i=0; i<destinationArrayLength; i++) {
		destinationArray.push(sourceArray[currentIndex]);
		if(++currentIndex >= sourceArrayLength) {
			currentIndex = 0;
		}
	}
	destinationArray = [];
}

余り方式で循環する関数test02。

function test02() {		// :void
	var currentIndex = 0;
	for (var i=0; i<destinationArrayLength; i++) {
		destinationArray.push(sourceArray[currentIndex]);
		currentIndex = ++currentIndex % sourceArrayLength;
	}
	destinationArray = [];
}

test01とtest02で違うところ

for文内の

if(++currentIndex >= sourceArrayLength) {
	currentIndex = 0;
}

currentIndex = ++currentIndex % sourceArrayLength;

のみですね。
そして、ここが今回のテストの勘所でもあります。

では、いよいよ計ってみます。

コメントに、とある回の出力を示します。

console.log('if文方式: ' + getTheFuncTime(test01, 5) + 'ms');	// if文方式: 468.6ms
console.log('余り方式: ' + getTheFuncTime(test02, 5) + 'ms');	// 余り方式: 512.6ms

結果

何度か計測した中では100%、「if文方式」の方が「余り方式」よりも良いパフォーマンスが得られました。
それぞれの配列の個数を変えても、概ね同じ比率です。
また、console.logをalertにしてIEでも計測してみましたが、実装による違いもないようです。

感想

新しい書き方(余り方式)を知ってテンションが上がっていた自分には残念な結果でしたが、よい勉強になりました。
エレガントというか、プログラムっぽい書き方(自分はそう思うのですが…)が必ずしも速いというわけではない。
でも、こういう構文糖にはもっとたくさん出会って、柔軟にプログラミング出来るようになりたいです。
今回の余り方式だって、他に使いどころがあるかも知れないし。

「そもそもテストの仕方がおかしいぞ!」などなどあれば、ツッコミ頂ければ幸いです><