今回は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外出しの場合も計測して追記させていただきます!
ありがとうございました。