今回はPHPで何気なく書いているコードを速度計測し、高速化が図れるようなコードを考察していきます。
普段私達が当たり前のように書いてるコード、意外と無駄が多かったりします。
一番身近なところだと標準出力のecho,print関数。
出力する時はどちらを使っても問題ありません。
でも実は大きな速度差が出てくるんです。
ということで今回は知ったらすぐ実践できる、
コードの高速化を検証を交えながら紹介します!
計測方法
//計測回数
define('COUNT',10);
//試行回数
define('TEST_COUNT',100000);
//小数点桁数
define('DECIMAL_DIGITS',10);
//平均値
$average = 0.0;
for($i = 0; $i < COUNT; $i++) {
$start = microtime(true);
for($j = 0; $j < TEST_COUNT; $j++) {
//計測対象
}
$end = microtime(true);
$result = $end - $start;
echo number_format($result,DECIMAL_DIGITS)."秒<br>";
$average += $result;
}
//平均値の出力
$average = number_format($average/COUNT,DECIMAL_DIGITS);
echo 'avarage:'. $average.'秒<br>';
//前回の計測結果(自己満)
session_start();
echo 'before:'.$_SESSION['before'].'秒';
//前回の計測結果を更新
$_SESSION['before'] = $average;はい、無駄に凝ったものを作りました。
概要としては10万回同じ処理を繰り返して1回分のタイムを計ります
そしてそれを10回繰り返し、最終的な平均値を算出します。
(簡単に計るのであればmicrotime関数を使った11~17行目で充分です。はい。)
実際に測ってみた
No.1 echo VS print
みんな大好き標準出力。果たしてどちらが速いのか!ファイッ
●echo関数
echo '';
avarage:0.0256559134秒
●print関数
print '';
avarage:0.0357182026秒
結果:echo関数の勝利
0.01秒差でechoの方が速かった。
そもそもprintは返り値があって、echoは返り値がない。
これが速度に関係しているのかもしれない。
No.2 ===演算子 VS ==演算子
PHP、javascript話者の一番の迷いどころ。
型の比較に厳しい===演算子、みんなに優しい==演算子。
どちらが速いのか!ファイッ
●===演算子
'1' === '1';
avarage:0.0387856722秒
●==演算子
'1' == '1';
avarage:0.0792219639秒
結果:===演算子の圧勝
なんと、倍近くの差が出ました。
==演算子は比較の際にキャストが発生するので、速度が落ちるそう。
型比較で地雷を踏むことも多いので===演算子を使いましょう!
No.3 foreach VS for+count
foreachがうまく使えないタイミング?でたまに使ってしまうfor+count
どちらが速いのか!ファイッ
●foreach
$arr = array('','','');
foreach($arr as $value) {
$value;
}avarage:0.0671128988秒
●for+count
$arr = array('','','');
for($k = 0; $k < count($arr); $k++) {
$arr[$k];
}avarage:0.2939522028秒
結果:foreachの圧勝
やはりcount関数をかませているのもあってか、forだと速度は落ちた。
No.4 foreach VS for+count 番外編
では次はハンデとして少し遅くなりそうなforeachのkeyを取得した場合と
for文のcount関数を初期化時にのみ使用した場合を戦わせてみましょう。ファイッ
●foreach $key=>$value
$arr = array('','','');
foreach($arr as $key => $value) {
$value;
}
avarage:0.0817322254秒
参考
valueのみ:0.0671128988秒
やはりkeyを取得させると少し遅くなるようです。
keyが不要の場合はvalueのみで回しましょう。
●for+count
$arr = array('','','');
for($k = 0,$cn = count($arr); $k < $cn; $k++) {
$arr[$k];
}avarage:0.1781846523秒
参考
countを毎回実行:avarage:0.2939522028秒
初期化時のみcount関数を実行させる方が倍近く速いですね。
結果:foreachを使おう(適当)
No.5 if VS switch
値で処理を分岐させるのに使ったりするifとswitch。
これもなかなか迷いどころなので戦わせてみましょう。ファイッ
●if
if('1' == '2') {
} else if('2' == '2') {
}avarage:0.1120637894秒
※PHPのswitch文は内部で==演算子を使ってるとのことなので
if文も==演算子で計測しました。
●switch
switch('2'){
case '1':
case '2':
}avarage:0.1080152988秒
結論:switchの勝利
とは言っても、一つ一つの結果を見てると誤差の範囲…?
ということで今回は5パターンの検証をしてみました。
意外と遅くなる処理を書いていた人もいるかと思います。僕もそうです。
是非、これを参考にコードの最適化をしてみてください!

コメント
普段javaばっかりでphp詳しくはないですが
No.3 は
$max = count($arr);
for($k = 0; $k < $max; $k++) {
じゃないとフェアじゃないかなぁと。。。
ご指摘ありがとうございます!
確かにcount関数の分フェアじゃないですよね。
ただ、今回の記事ではforeachとforの厳密な速度を比較するというより、「このアンチパターンだとこれだけ遅いですよ」という意味合いがあるので、このままとさせてください。
言葉足らずで申し訳ありません。
近々count外出しの場合も計測して追記させていただきます!
ありがとうございました。