LoginSignup
9
3

More than 3 years have passed since last update.

PHPの文字列連結の中で最速を考えてみる

Last updated at Posted at 2020-12-08

はじめに

こんにちは、普段は業務で求人系サービスの開発を行なっている@taku-0728です。
今回はいくつかあるPHPの文字列連結のやり方について、一番早いやり方を考えてみます。
あくまで一例なので、他に「こんなやり方もあるよ!」等あればコメントにてご指摘いただければ幸いです。
よろしくお願いいたします。

12/8 追記 @il9437さんからのコメントを元に再度検証しています。

背景

業務中にPHPで文字列連結をする場面があったのですがその時にふと
「普段は何も考えず'私の名前は' .$name .'です。'とか書いてるけど、
"私の名前は $name です。"とか書いても結果は同じだしどっちが早いんだろう」
と思ったので検証してみます。

準備

今回は下記3パターンの文字列連結の書き方を準備します。

パターン1(シングルクォート)

パターン1はシングルクォートと連結演算子(.)で連結したパターンです。
サンプルコードはこちら

pattern1.php
<?php
// パターン1
$dogName = 'ポチ';
$startTime1 = microtime(true);

for($j = 0; $j < 10000; $j++){
  // コメントにて指摘をいただいたためコードを一部変更
  // $tmp = '私が飼っている犬の名前は' .$dogName .'です。';
  $tmp = '私が飼っている犬の名前は'.$dogName.$j.'です。';
}

$endTime1 = microtime(true);
$ret1 = $endTime1 - $startTime1;
?>

パターン2(変数展開)

パターン2は文字列の中で変数展開したパターンです。
サンプルコードはこちら

pattern2.php
<?php
// パターン2
$dogName = 'ポチ';
$startTime2 = microtime(true);

for($j = 0; $j < 10000; $j++){
  // コメントにて指摘をいただいたためコードを一部変更
  // $tmp = "私が飼っている犬の名前は $dogName です";
  $tmp = "私が飼っている犬の名前は${dogName}${j}です";
}

$endTime2 = microtime(true);
$ret2 = $endTime2 - $startTime2;
?>

パターン3(ダブルクォート)

パターン3はダブルクォートと連結演算子(.)で連結したパターンです。
サンプルコードはこちら

pattern3.php
<?php
// パターン3
$startTime3 = microtime(true);

for($j = 0; $j < 10000; $j++){
  // コメントにて指摘をいただいたためコードを一部変更
  // $tmp = "私が飼っている犬の名前は" .$dogName ."です。";
  $tmp = "私が飼っている犬の名前は".$dogName.$j."です。";
}

$endTime3 = microtime(true);
$ret3 = $endTime3 - $startTime3;
?>

検証

上記3パターンのコードを実行し、速度を検証してみます。
複数回実行した時に必ずしも同じ速度になるとは限らないので、今回は10回実行した結果の平均値で検証を行います。
それを踏まえた最終的なコードは下記です。
雑に考えただけなので、より簡潔な書き方があればコメントにてご指摘いただければ幸いです。

test.php
<?php
$dogName = 'ポチ';
$sum1 = 0;
$sum2 = 0;
$sum3 = 0;

for($i = 0; $i < 10; $i++){
  // パターン1
  $startTime1 = microtime(true);

  for($j = 0; $j < 10000; $j++){
    // コメントにて指摘をいただいたためコードを一部変更
    // $tmp = '私が飼っている犬の名前は' .$dogName .'です。';
    $tmp = '私が飼っている犬の名前は'.$dogName.$j.'です。';
  }

  $endTime1 = microtime(true);
  $ret1 = $endTime1 - $startTime1;
  $sum1 += $ret1;

  // パターン2
  $startTime2 = microtime(true);

  for($j = 0; $j < 10000; $j++){
    // コメントにて指摘をいただいたためコードを一部変更
    // $tmp = "私が飼っている犬の名前は $dogName です";
    $tmp = "私が飼っている犬の名前は${dogName}${j}です";
  }

  $endTime2 = microtime(true);
  $ret2 = $endTime2 - $startTime2;
  $sum2 += $ret2;

  // パターン3
  $startTime3 = microtime(true);

  for($j = 0; $j < 10000; $j++){
    // コメントにて指摘をいただいたためコードを一部変更
    // $tmp = "私が飼っている犬の名前は" .$dogName ."です。";
    $tmp = "私が飼っている犬の名前は".$dogName.$j."です。";
  }

  $endTime3 = microtime(true);
  $ret3 = $endTime3 - $startTime3;
  $sum3 += $ret3;
}

$avg1 = $sum1 / 10;
$avg2 = $sum2 / 10;
$avg3 = $sum3 / 10;

echo("パターン1:平均時間:" .$avg1 ."秒\n");
echo("パターン2:平均時間:" .$avg2 ."秒\n");
echo("パターン3:平均時間:" .$avg3 ."秒\n");
?>


結果

10回実行した平均値は下記のようになりました。

パターン1:平均時間:0.00032708644866943秒
パターン2:平均時間:0.00034801959991455秒
パターン3:平均時間:0.00032320022583008秒

パターン2の変数展開が一番遅いのは予想通りでしたが、パターン1のシングルクォートよりもパターン3のダブルクォートの方が(わずかではありますが)速かったのは意外でした。
環境や実際のコードにもよるのでこの結果が全てのパターンに当てはまるとは限りませんが、参考にしてみてください。

12/8 追記 コメントにてご指摘をいただき、追加検証したところ最初と異なった結果になったので修正しています。

パターン1:平均時間:0.00068399906158447秒
パターン2:平均時間:0.00056874752044678秒
パターン3:平均時間:0.00066797733306885秒

パターン2の変数展開が一番遅いと予想していましたが、(わずかではありますが)一番早い結果になって正直驚きました。環境や実際のコードにもよるのでこの結果が全てのパターンに当てはまるとは限りませんが、参考にしてみてください。
なぜこのような結果になるのかは機会があれば改めてまとめてみようと思います。

まとめ

今回はPHPの文字列連結はどのやり方が一番早いのか、ふと疑問に思ったので検証してみました。
結果の方にも記載しましたが、あくまで一例ですので、参考程度にお考えください。
雑に書いたコードですので、もし誤りや改善点があればお手数ですがコメントにてご指摘いただけると幸いでございます。
ありがとうございました。

9
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3