[PHP] function() がどれほど遅いか調べてみた

似たようなコードを繰り返して使うような場合は、function() で関数化するとコードが冗長的にならずに、読みやすく作りやすいプログラムになります。

さて、PHPに限らずプログラムを書くに当たって必須ともいえるfunction() ですが、ちょっと気になることがあります。
function() にはオーバーヘッドがあるということ。

どういうことかというと、プログラムは通常、ファイルの上から下に向かって実行されていきます。
その途中に、 $hoge = getHoge(); のように関数があると、コンピュータは getHoge() が”どこにあるのか探して”、そしてgetHoge()の中を実行して戻ってきます。

関数になってなければ、次はスグ下の行に移ればいいだけであることを考えると、全く違う場所に書かれている getHoge() を探さなきゃいけないってことはなんとなくイメージできるのではないでしょうか?

この、”どこにあるのか探す”という処理のことを、オーバーヘッドと呼びます。

function()を使うのと使わないのとでは、function() にするほうが遅くなるのは、予想できるかと思います。
で、問題はどの程度のオーバーヘッドがあるか?ということですね。

オーバーヘッドが無視できるくらいに小さいのであれば、多少オーバーヘッドがかかったとしても、function()化するメリットは充分にあります。

で、テストコード。説明は、コードの下に続きます。

<?php
// この数字をPCのスペックに合わせて大きくしてください
$LoopCount = 100;

// function無し
$Start = getMicrotime();
for ($i = 0; $i 0) {
if (strtolower($Type) == "post"){
$hoge = str_replace("+", "%2B", $hoge);
$hoge = urldecode($hoge);
}
$hoge = trim(mb_convert_encoding($hoge, "utf-8", "utf-8, JIS, eucjp-win, sjis-win, utf-8"));
$hoge = htmlspecialchars($hoge);
}
}
echo 'なし: ' . ($End1 = (getMicrotime() - $Start)) . '秒<hr />';

// function有り
$Start = getMicrotime();
for ($i = 0; $i 0) {
if (strtolower($Type) == "post"){
$ret = str_replace("+", "%2B", $ret);
$ret = urldecode($ret);
}
$ret = trim(mb_convert_encoding($ret, $Enc, $Enc.", JIS, eucjp-win, sjis-win, utf-8"));
$ret = htmlspecialchars($ret);
return $ret;
}
return "";
}

echo 'あり: ' . ($End2 = (getMicrotime() - $Start)) . '秒<hr />';

echo 'functionなしが ' . ($End2 - $End1) . ' 秒早い';

// 現在のマイクロ秒を取得
function getMicrotime()
{
list($msec, $sec) = explode(" ", microtime());
return ((float)$sec + (float)$msec);
}
?>

 

実行結果を見る

少々長くなってしまいましたが、実践的な意味で、私個人として使用頻度の高いfunction()でテストしてみました。

上のコードは、ブラウザから get で送られた値(name)を $_GET["name"]) で取得し、サニタイズ、デコード処理などを行うところまで含めています。

get,post,cookieの値を、getOutsideVariable()を通して取得することで、自分が本来欲しい形での値を取得できることになります。

function() を利用しない場合は、getOutsideVariable()と同じ結果を取得できる必要最低限のコードにしています。これはfunction()にしないなら、実践的なこととして余計なコードを書くハズがないから、という理由に基づいています。

さて、結果ですが、function()ありのほうが約2倍遅いですね。
ですが、function()ありの速度を見てみると、約0.00033秒となっています。
ちなみに、function()を100回繰り返しての結果です。

問題は、function()のオーバーヘッドですので、function()あり と なし の差がオーバーヘッドになります。まぁ実際は、get,post,cookieを1つにまとめるための分岐コードなどもありますが、そういうのも含めての【処理時間の差】を比べるのが関数化する意味合いを考えても自然かと思います。

処理時間の差は、約 0.00017秒です。繰り返しになりますが、100回繰り返しての結果です。

で、まぁ私なりの結論ですが、function()化することで遅くなることよりも、function()を使わないことでコードが増えることのほうがデメリットが高いという考えが確信になりました。

ちなみに・・・一番最初にこんなテストコードを作ってみたけど、これって意味ないじゃん!という経緯の後、上記の実践的なコードでテストし直しました。

for ($i = 0; $i &lt; $LoopCount; $i++){
$hoge = $i + 10;
}
for ($i = 0; $i &lt; $LoopCount; $i++){
$hoge = getHoge($i);
}
function getHoge($i){ return $i + 10; }

実行結果を見る】 ($LoopCount = 1000 です)