3
2

結論

関数呼び出し分のオーバーヘッドで遅い

環境情報

Windows11機から、WSL2でUbuntu20.04を立ち上げています。
CPU: 13th Gen Intel(R) Core(TM) i7-13700F

# php -v
]PHP 8.1.2-1ubuntu2.14 (cli) (built: Aug 18 2023 11:41:11) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.2-1ubuntu2.14, Copyright (c), by Zend Technologies

array_push()は遅い

「PHP 配列 追加」と検索するとまず紹介されるのがarray_push()ですが、これは遅すぎの王、遅すぎキングと有名ですね。

代わりに$(変数名)[] = (追加要素)という文法を推奨されます。

実際に時間計測してみましょう。

test.php
<?php

$time_start_0 = microtime(true);
for ($cnt = 0; $cnt < 1000000; $cnt++){
        $a = [1,2,3,4,5,6,7,8,9,10];
        array_push($a, 11);
}
$time_0 =  microtime(true) - $time_start_0;
var_dump($time_0);

$time_start_1 = microtime(true);
for ($cnt = 0; $cnt < 1000000; $cnt++){
        $a = [1,2,3,4,5,6,7,8,9,10];
        $a[] = 11;
}
$time_1 =  microtime(true) - $time_start_1;
var_dump($time_1);

//何倍速くなったか
var_dump($time_0 / $time_1);                               
結果
# php test.php
float(0.03344011306762695)
float(0.021086931228637695)
float(1.5858216970998926)

1.5倍と出ました。人によっては3倍になるらしいですね

しかし、これは両者とも時間計算量はO(1)とのことです。

なぜ?

phpdbgで下記コードの中間コードを表示してみましょう。

test.php
<?php

$a = [];

array_push($a, 1);

$a[] = 2;
中間コード
# phpdbg test.php
prompt> print e
[Context /test.php (8 ops)]

$_main:
     ; (lines=8, args=0, vars=1, tmps=3)
     ; /test.php:1-8
L0003 0000 ASSIGN CV0($a) array(...)
L0005 0001 INIT_FCALL 2 112 string("array_push")
L0005 0002 SEND_REF CV0($a) 1
L0005 0003 SEND_VAL int(1) 2
L0005 0004 DO_ICALL
L0007 0005 ASSIGN_DIM CV0($a) NEXT
L0007 0006 OP_DATA int(2)
L0008 0007 RETURN int(1)

L0005の中間コードを見てください。5行目はarray_push()でしたね。
上から

  • array_pushという名前の関数を拾ってくる
  • 引数$aの参照を送信
  • 引数2を送信
  • 関数の処理を呼び出し(DO_ICALL
    という感じのニュアンスです。(厳密にはたぶん違います)

L0007$a[] = 2のコードですが、 実は これはL0005 0004DO_ICALLと同内容です
つまり、array_push()関数呼び出しの分だけ 無駄な処理を行っているわけです。

一方、$a[] = 2はオペレーターに処理を埋め込まれている(?)ので、 余計な処理がない ということですね。

このような標準関数の中間コード変換問題については、こちらの記事が面白いです:ZendEngineにえこひいきされる標準関数たち (前篇)

3
2
0

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
3
2