HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

文字列連結のパフォーマンス比較

そういえば計ったことなかったなぁ‥と思い立って、いくつかのパターンで計ってみたメモ。

実行環境は、自宅のXenServer上に載せた以下のVM環境。

ケース1:文字列連結演算子とダブルクォーテーションと

プログラムの全体は以下のような感じ。

n,test1,test2
<?php

for ($n = 10000; $n <= 50000; $n += 5000) {
set_time_limit(120);
    // test1
    $s1 = microtime(true);
    $str = '';
    for ($i = 0; $i < $n; ++$i) {
        $str = $str . 'a' . $i . 'b';
    }
    $e1 = microtime(true);

    // test2
    $s2 = microtime(true);
    $str = '';
    for ($i = 0; $i < $n; ++$i) {
        $str = "{$str}a{$i}b";
    }
    $e2 = microtime(true);

    printf("%d,%.3f,%.3f\n",
        $n, $e1 - $s1 , $e2 - $s2);
}

文字列を

        $str = $str . 'a' . $i . 'b';

で連結するか

        $str = "{$str}a{$i}b";

で連結するかの違い。

実行すると、以下のような出力が得られる。

n,test1,test2
10000,0.075,0.029
15000,0.228,0.065
20000,0.445,0.120
25000,0.873,0.199
30000,1.422,0.300
35000,2.168,0.451
40000,3.023,0.581
45000,2.802,0.739
50000,3.962,0.938

グラフにしてみるとこんな感じ。

f:id:hhelibex:20160609133252p:plain

ケース2:ダブルクォーテーションと複合演算子

プログラムの全体は以下のような感じ。

n,test2,test3,test4
<?php

for ($n = 10000; $n <= 100000; $n += 5000) {
set_time_limit(120);
    // test2
    $s2 = microtime(true);
    $str = '';
    for ($i = 0; $i < $n; ++$i) {
        $str = "{$str}a{$i}b";
    }
    $e2 = microtime(true);

    // test3
    $s3 = microtime(true);
    $str = '';
    for ($i = 0; $i < $n; ++$i) {
        $str .= 'a' . $i . 'b';
    }
    $e3 = microtime(true);

    // test4
    $s4 = microtime(true);
    $str = '';
    for ($i = 0; $i < $n; ++$i) {
        $str .= "a{$i}b";
    }
    $e4 = microtime(true);

    printf("%d,%.3f,%.3f,%.3f\n",
        $n, $e2 - $s2, $e3 - $s3, $e4 - $s4);
}

文字列を

        $str = "{$str}a{$i}b";
        $str .= 'a' . $i . 'b';
        $str .= "a{$i}b";

のように連結するという3パターン。1つ目は、ケース1で早かった方と同じ。

実行すると、以下のような出力が得られる。

n,test2,test3,test4
10000,0.016,0.001,0.001
15000,0.034,0.002,0.002
20000,0.069,0.003,0.003
25000,0.102,0.004,0.003
30000,0.149,0.004,0.004
35000,0.210,0.005,0.005
40000,0.281,0.006,0.005
45000,0.363,0.006,0.006
50000,0.455,0.007,0.007
55000,0.556,0.008,0.008
60000,0.668,0.009,0.008
65000,0.782,0.009,0.009
70000,0.916,0.010,0.009
75000,1.054,0.011,0.011
80000,1.212,0.011,0.011
85000,1.364,0.012,0.012
90000,1.534,0.013,0.012
95000,1.723,0.013,0.013
100000,1.915,0.014,0.014

‥圧倒的差である。一応グラフにしてみる。

f:id:hhelibex:20160609134310p:plain

test3のグラフは隠れて見えないが、test4の下に隠れている。

結局‥

  • ケース2の結果を見る限り、長い文字列$strが右辺に出てくるときの評価にコストがかかるのだろうか。
  • ケース1の結果から、同じ長い文字列が右辺に現れざるを得ない場合は、文字列連結演算子の処理の方がコストがかかるということか。

正直、ここまで差が出るとは思わなかったので、文字列連結処理を書くときには、これからは気を使うようにしようと思う。