あなたのコード、激遅ぷんぷん丸?今すぐできる7つのチェック項目 PHP編

あなたのコード、激遅ぷんぷん丸?今すぐできる7つのチェック項目 PHP編php_logo

みなさん、こんにちは。

GeNERACEのピンキリエンジニアこと、ひろゆきです。

ここのところPHPを書いてるんですが、同じ処理を書くとしても、どの関数を使えば良いのか分からないことがありました。

たとえば、繰り返し処理を書くにしてもfor, foreach, whileと3種類もあります。

いったいどれを使えば良いの?(´・ω・`)

分からないなら調べれば良い。

ということで、弊社環境にて処理速度の検証してみました。

(この辺ってググってみても、ソースが古かったりしてたので、あえて調べました)

実行環境:
PHP 5.3.3
AWS EC2 m1.small

1.ループ処理を比較

まずは基本中の基本。

for, foreach, whileのどれを使うべきなのか。

$this->testArray = range(0, 10000000);

$x = 0;
foreach ($this->testArray as $num) {
    ++$x;
}

$x = 0;
while (list(, $num) = each($this->testArray)) {
    ++$x;
}

$x = 0;
$count = count($this->testArray);
for ($i=1; $i<=$count; ++$i) {
    ++$x;
}

1,000,000回の繰り返しを実行して比較しました。

for     0.56558704376221sec
foreach 0.42324614524841sec
while   4.60147857666020sec

あれ?

「php while foreach 速度」でググった結果と違う!!

いつの間にかforeachは進化していたのか。。。

いつからなのか気になるので、知ってる方がいましたら教えてください。

2.インクリメントの前置と後置を比較

++$i と書くべきか $i++ と書くべきか。

こちらは10,000,000回の繰り返しを実行して比較しました。

++$i 1.5849459171295sec
$i++ 1.7777631282806sec

前置の方が速いですね。

特別な理由がない限りは前置を使うべきのようです。

3.if else と 三項演算子を比較

可読性など、好みが別れるとは思いますが、10,000,000回の繰り返しを実行して比較しました。

if ($num % 2 == 0) {
    $result = true;
} else {
    $result = false;
}

$result = $num % 2 == 0 ? true : false;

結果は・・・

if else 3.5520250797272sec
三項演算子 3.2163460254669sec

少しだけ三項演算子の方が速いようですね。

可読性が低くならない程度に使用したほうが良いのかも。

4.if else と switch を比較

else if を複数書くのはエレガントではないと思いますが、switchとどちらが速いのか。

$res = $num % 3;
if ($num == 0) {
	++$res;
} else if ($num == 1) {
	++$res;
} else if ($num == 2) {
	++$res;
}

$res = $num % 3;
switch ($res) {
    case 0:
        ++$res;
        break;
    case 1:
        ++$res;
        break;
    case 2:
        ++$res;
        break;
}

結果は・・・

if else 4.4547448158264sec
switch 4.4178919792175sec

回数にもよると思うのですが、3パターンだと少しだけswitchの方が速いようですね。

5.== と === の比較

評価式にて、型までは考慮しない == で評価するのか、=== で型まで評価するのか。

$res = $num % 2;
if ($num == 0) {
    ++$res;
} else if ($num == 1) {
    ++$res;
}

$res = $num % 2;
if ($num === 0) {
    ++$res;
} else if ($num === 1) {
    ++$res;
}

結果は・・・

==  3.97003698349sec
=== 4.1816999912262sec

== の方が少し速いようですね。

厳密な評価が必要な場合の時のみ、===を使用するほうが良さそうですね。

6.empty と count の比較

DBからデータを取得した結果(配列)の件数チェックなどで、

$list = array();
if (count($list) == 0) {
    return false;
}

と件数をチェックするのか

$list = array();
if (empty($list)) {
    return false;
}

とするのか。

結果は・・・

count 0.95642995834351sec
empty 0.35932707786560sec

emptyの方が約3倍くらい速いようですね。

ただし、これはデータが0件の場合です。

10件の場合も確かめてみました。

count 2.2545471191406sec
empty 1.8845028877258sec

あれ?

差が縮まっている。

emptyはデータが空かどうかの判定をする処理のため、そんなに処理時間が変わらないかと思っていましたが、意外にも要素数に関係があるようです。

countは数える処理をするため、想定通り、処理速度が遅くなっています。

ということで、array型の0件チェックはemptyの方が良さそうですね。

7.isset と array_key_exists の比較

配列にKeyが存在するかを、両関数で判定することが可能です。

$list = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
// keyが存在する
if (isset($list['c'])) {
}
// keyが存在しない
if (isset($list['x'])) {
}

$list = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
if (array_key_exists('c', $list)) {
}
if (array_key_exists('x', $list)) {
}

結果は・・・

isset 1.5214328765869sec
array_key_exists 2.5436730384827sec

issetの方が速くて良さそうですね。

ただし、要素がnullの場合は判定結果が変わるので注意する必要があります。

まとめ

PHPの変数は何が格納されているか分かりません。

分かりませんというより、なんでも入ります。

これは非常に気をつけなければいけませんが、処理上、この型が必ず返ってくるということもあります。

そういった時に今回のように検証を行なっておけば、どの関数を使用した書き方がベストなのかが判断可能になるわけです。

Viva 検証!!

しかし、以前に聞いて知っていたものと違う結果になったりと、今回の検証はためになりました。

PHPって怖いなぁww

以上、ここまで読んで頂き、ありがとうございました!

おまけ

簡単に速度確認が出来るプログラムを下記に載せておきました。

※実行環境によって差が出る可能性がありますので、ご使用の際は内容をご確認ください。
http://blog.generace.co.jp/php/speed_test.php
gist

不備、ご指摘などありましたら、ご連絡くださいませ。

3 thoughts on “あなたのコード、激遅ぷんぷん丸?今すぐできる7つのチェック項目 PHP編

  1. Pingback: 【キニナルハナシ】2013/06/23 | PGMY Input Output Life

  2. Pingback: 【おはあぷ】リリース2週目!そのダウンロード数と収益は!? | あぷまがどっとねっと

  3. Pingback: 2013年PHPの話題を一挙に振り返るまとめ | Engine Yard Blog JP

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です