配列の作成方法による速度の比較

JavaScriptで新しく配列を作成する際の方法により、速度に違いはあるのでしょうか?調べてみました。

まずはnew Array()を使用した方法です。

function test1 () {
	var array = new Array();
}

次に[]を使用して作成します。

function test2 () {
	var array = [];
}

この二つの関数を100万回呼び出した時の結果は以下の通りです。

OS ブラウザ バージョン test1 test2
Mac OS X Safari 5.0 0.2848 0.2721
Mac OS X Firefox 3.6 0.1825 0.4413
Mac OS X Chrome 5.0 0.0248 0.0143
Windows Internet Explorer 8.0 1.2156 1.0547
Windows Firefox 3.6 0.1524 0.5879
Windows Chrome 5.0 0.0265 0.0146

まず、Chromeが優秀すぎます。Mac・Winともに桁違いの速さです。そしてFirefoxだけがtest1の方が速いという結果に。しかもその差はかなりの大きさです。IEは置いといて、Safariが微妙な差で、Chromeが十分に速い事を考えると、これはおとなしくnew Array()を使った方がいいのかもしれません。

Mac: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB)
Windows: Parallels Desktop 5

整数の絶対値の求め方の比較

JavaScriptで整数の絶対値を求める際に、Math.abs()を使用する場合と使用しない場合の速度を比較してみました。

まずは普通にMath.abs()を使用した方法です。

function test1 () {
	var num = -10;
	var a = Math.abs(num);
}

次に条件分岐した場合。

function test2 () {
	var num = -10;
	var a = num < 0 ? -num : num;
}

最後にビット演算を使用した場合。

function test3 () {
	var num = -10;
	var a = (num ^ (num >> 31)) - (num >> 31);
}

これらの関数を各種ブラウザで100万回呼び出した時の時間がこちらです。

OS ブラウザ バージョン test1 test2 test3
Mac OS X Safari 5.0 0.0268 0.0193 0.0164
Mac OS X Firefox 3.6 0.0171 0.0039 0.0108
Mac OS X Chrome 5.0 0.0171 0.0091 0.0087
Windows Internet Explorer 8.0 0.7109 0.4203 0.4750
Windows Firefox 3.6 0.0140 0.0046 0.0088
Windows Chrome 5.0 0.0185 0.0120 0.0134

IEを除いてみんな高速ですので、Math.abs()で良さそうなのですが、より速さを求める人はtest2かtest3の方法をオススメします。小数の絶対値が必要な人はtest2を使ってください。

Mac: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB)
Windows: Parallels Desktop 5

if 〜 else if の順番による速度比較

if ~ else if の条件分岐で、複数の条件があり条件に当てはまる可能性にあらかじめ予想がつく場合、条件を指定する順番で速度は変わるのでしょうか。

まずは可能性の少ないもの順で条件を指定してみます。

function test1 () {
	var rnd = Math.random();
	var result = 0;
	if (rnd < 0.01) {
		result = 1;
	} else if (rnd < 0.02) {
		result = 2;
	} else if (rnd < 0.04) {
		result = 3;
	} else if (rnd < 0.08) {
		result = 4;
	} else if (rnd < 0.16) {
		result = 5;
	} else {
		result = 6;
	}
}

そして可能性の高いもの順で条件を指定してみます。

function test2 () {
	var rnd = Math.random();
	var result = 0;
	if (rnd >= 0.16) {
		result = 6;
	} else if (rnd >= 0.08) {
		result = 5;
	} else if (rnd >= 0.04) {
		result = 4;
	} else if (rnd >= 0.02) {
		result = 3;
	} else if (rnd >= 0.01) {
		result = 2;
	} else {
		result = 1;
	}
}

これら二つの関数を100万回呼び出した際にかかった時間はこちら。

OS ブラウザ バージョン test1 test2
Mac OS X Safari 5.0 0.0384 0.0349
Mac OS X Firefox 3.6 0.0793 0.0587
Mac OS X Chrome 5.0 0.0441 0.0349
Windows Internet Explorer 8.0 3.9332 3.2136
Windows Firefox 3.6 0.2278 0.1923
Windows Chrome 5.0 0.1935 0.1382

多かれ少なかれtest2の方が高速ですね。可能性の高い事が予想される条件は、上の方に持っていった方が良さそうです。

Mac: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB)
Windows: Fujitsu FMV Intel Atom CPU Z530 1.6GHz (2GB)

二重引用符内に変数を使用するコスト

PHPの文字列で、二重引用符(ダブルクォーテーション)の中に変数を含める場合と、含めない場合の速度比較をしてみました。

まずは簡単な例から。

$animal = "cat";
for ($i=0; $i<1000000; $i++) {
	$str = "This is a $animal.";
}
平均:0.17689秒

そして二重引用符の外に変数を出してみると・・・。

$animal = "cat";
for ($i=0; $i<1000000; $i++) {
	$str = "This is a " . $animal . ".";
}
平均:0.17210秒

若干外に変数がある方が速いです。約97%の時間に短縮されました。でもこのくらいなら無視してもイイかもしれませんね。それでは二重引用符内に複数の変数がある場合はどうなるでしょうか?

変数を4つ用意してみました。

$a = "four";
$b = "words";
$c = "needing";
$d = "love";
for ($i=0; $i<1000000; $i++) {
	$str = "If I am $a $b then I am $c of your $d";
}
平均:0.55091秒

そしてそれを同じように二重引用符の外に置いてみると・・・。

$a = "four";
$b = "words";
$c = "needing";
$d = "love";
for ($i=0; $i<1000000; $i++) {
	$str = "If I am " . $a . " " . $b . " then I am " . $c . " of your " . $d;
}
平均:0.52004秒

これまた速いは速いんだけど微妙な差ですね。こちらは約94%に短縮です。どうやら変数の個数に比例して速くはなるようですね。もしソースが見にくくならないのなら、変数は二重引用符の外に出しておいた方がイイかもしれません。

Apache: 2.2.14
PHP: 5.3.1
OS: Mac OS X 10.6.4
Server: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB 1,067 MHz)

文字列連結のコスト

JavaScriptで文字列を連結する際にかかる時間を調べてみました。

まずはシンプルな連結から。

function test1 () {
	var str = '';
	str += 'こんにちは。';
}

次に文字列を長くしてみました。

function test2 () {
	var str = '';
	str += 'おはようございます。こんにちは。こんばんは。ありがとうございます。おやすみなさい。';
}

文字列を2つに分割してみました。

function test3 () {
	var str = '';
	str += 'おはようございます。こんにちは。こんばんは。' + 'ありがとうございます。おやすみなさい。';
}

さらに細かく文字列を分割してみました。

function test4 () {
	var str = '';
	str += 'おはようございます。' + 'こんにちは。' + 'こんばんは。' + 'ありがとうございます。' + 'おやすみなさい。';
}

最後に分割した文字列を1つずつ連結してみました。

function test5 () {
	var str = '';
	str += 'おはようございます。';
	str += 'こんにちは。';
	str += 'こんばんは。';
	str += 'ありがとうございます。';
	str += 'おやすみなさい。';
}

これらの関数を100万回呼び出した時の時間が以下の通りです。

OS ブラウザ バージョン test1 test2 test3 test4 test5
Mac OS X Safari 5.0 0.021 0.020 0.225 0.343 0.926
Mac OS X Firefox 3.6 0.014 0.014 0.014 0.014 1.174
Mac OS X Chrome 5.0 0.028 0.028 0.056 0.109 0.098
Windows Internet Explorer 8.0 3.304 3.273 5.588 11.358 11.767
Windows Firefox 3.6 0.042 0.041 0.041 0.041 3.977
Windows Chrome 5.0 0.081 0.074 0.268 0.501 0.388

Firefox以外のブラウザでは連結数を多くするほど遅くなりますね。またFirefoxやSafariでは行を分けて連結すると遅くなってしまうようです。スクリプトの見やすさとの兼ね合いもあると思いますが、無駄に分割して連結している箇所は一つにまとめた方が良さそうです。

Mac: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB)
Windows: Fujitsu FMV Intel Atom CPU Z530 1.6GHz (2GB)

とある整数が偶数かどうかを判定

JavaScriptで、とある整数と分かっている数値があって、その整数が偶数かどうかを判定する方法2種類の速度比較です。

一つ目は%(余り)を使った方法。2で割った余りが0なら偶数という考え方です。この関数に数字を投げて、trueならばそれは偶数という事です。

function test1 (num) {
	return num % 2 == 0 ? true : false;
}

もう一つはビット演算を使用した方法です。こちらも同じく数字を投げてtrueならば偶数です。

function test2 (num) {
	return (num & 1) == 0 ? true : false;
}

上記2つの関数を100万回呼び出した時の時間が以下の通りです。

OS ブラウザ バージョン test1 test2
Mac OS X Safari 5.0 0.227 0.179
Mac OS X Firefox 3.6 0.314 0.129
Mac OS X Chrome 5.0 0.401 0.087
Windows Internet Explorer 8.0 2.652 2.059
Windows Firefox 3.6 0.305 0.026
Windows Chrome 5.0 0.336 0.035

どのブラウザもビット演算(test2)を使用する方が速いですね。IEが激遅なのは気にしないでおきます。ちなみに判定する数値に小数が含まれる可能性がある場合は、ビット演算の方は小数点以下が切り捨てられますので正確に判定できません。ご注意ください。

Mac: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB)
Windows: Fujitsu FMV Intel Atom CPU Z530 1.6GHz (2GB)

array_pushと$array[]

PHPで配列に値を追加する方法、2種類の速度比較です。

まずはarray_pushを使用してみました。メモリの都合上、10万回のリピートです。

$array = array();
for ($i=0; $i<100000; $i++) {
	array_push($array, $i);
}
平均0.06376秒

次に$array[]で追加してみます。同じく10万回リピートします。

$array = array();
for ($i=0; $i<100000; $i++) {
	$array[] = $i;
}
平均0.04212秒

結果、$array[]の方がarray_pushより1.5倍程度速いです。

Apache: 2.2.14
PHP: 5.3.1
OS: Mac OS X 10.6.4
Server: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB 1,067 MHz)

array_key_existsとisset

PHPで配列にキーが含まれているかを判定する関数array_key_existsと、issetの速度比較です。

最初に使用するデータを準備します。

$array = array();
for ($i=0; $i<100000; $i++) {
	$array[$i] = 1;
}

そしてまずはarray_key_existsから。100万回リピートさせてみます。

for ($i=0; $i<1000000; $i++) {
	$flag = array_key_exists(1000, $array);
}
平均0.28056秒

次にissetで試してみます。同じく100万回リピートします。

for ($i=0; $i<1000000; $i++) {
	$flag = isset($array[1000]);
}
平均0.07986秒

結果、issetの方がarray_key_existsより3.5倍程度速いです。

Apache: 2.2.14
PHP: 5.3.1
OS: Mac OS X 10.6.4
Server: MacBook Pro 13インチ 2.66GHz Intel Core 2 Duo (8GB 1,067 MHz)