読者です 読者をやめる 読者になる 読者になる

PHPのarray_pushが鼻血出るくらい遅い件

結構な回数ブン回るループを書いていて、ふとarray_pushのマニュアルを読んでみると・・・

「大変遅いから$hoge[$num]で突っ込んだほうが良いよ」

なんてことが書かれている事に気づいた。

 

あれ? そんな違うの??

いっちょ試すか。

 

結論からすると、3倍近い差でarray_pushが遅い。

猛烈に遅い!!!

 

とりあえず以下の様なコードを書いて動かしてみた。

FuelPHP用の記述がなんぼかあるが、意味は伝わるかと。

 

     public function action_apush()
    {
        $max = 500000;
        $a = array();
        $b = array();
        $c = array();
        $t = array();

        $pu = "hogefugapiyo";

        // array_push
        $t[0][0] = microtime(true);
        for($i = 0; $i < $max; $i++)
        {
            array_push($a, $pu);
        }
        $t[0][1] = microtime(true);
        $t[0]['tleft'] = $t[0][1] - $t[0][0];
        unset($a);    // memory溢れるので

        // count direct
        $t[1][0] = microtime(true);
        for($i = 0; $i < $max; $i++)
        {
            $b[count($b)] = $pu;
        }
        $t[1][1] = microtime(true);
        $t[1]['tleft'] = $t[1][1] - $t[1][0];
        unset($b);    // memory溢れるので

        // direct
        $t[2][0] = microtime(true);
        for($i = 0; $i < $max; $i++)
        {
            $c[$i] = $pu;
        }
        $t[2][1] = microtime(true);
        $t[2]['tleft'] = $t[2][1] - $t[2][0];
        //unset($c);    // memory溢れるので

        // 賢く?
        //$c = array();    // ええい面倒だ
        $t[3][0] = microtime(true);
        $acnt = count($c);    // 途中から続行してみよう
        for($i = 0; $i < $max; $i++)
        {
            $c[$acnt + $i] = $pu;
        }
        $t[3][1] = microtime(true);
        $t[3]['tleft'] = $t[3][1] - $t[3][0];
        unset($c);

        $output_twig = 'common/json.twig';
        $data['result'] = $t;
        return Response::forge(View::forge($output_twig, $data));

    }

 

んで、実行結果は・・・・

・array_pushで追加した場合(561ms)

{"0":1395989176.1882,"1":1395989176.7498,"tleft":0.56161093711853}

 

・毎回countして末尾に追加した場合(500ms)

{"0":1395989176.7638,"1":1395989177.2642,"tleft":0.50038194656372}

 

・0番目から普通に追加していった場合(157ms)

{"0":1395989177.2795,"1":1395989177.4374,"tleft":0.15785098075867}

 

・最初にcountしてそっからインクリメント値を足して追加していった場合(188ms)

{"0":1395989177.4374,"1":1395989177.6254,"tleft":0.18804693222046}

 

最後の計測結果は、空のarrayをカウントしてからのスタートだとあまり意味がなさそうなので、3番目の結果作られたArrayの後ろに追加するようにしてみた。

 

この結果見ると、array_pushはやめとけって結論になるなぁ。

差がでかすぎる。。。

中で何をしていたらこんなに遅くなるんだろう。逆に興味が湧いてきました。

 

さて、今日はこの辺で。