web-dev-qa-db-ja.com

PHPオブジェクトvs配列-反復中のパフォーマンス比較

私は膨大な量のPHPを繰り返し処理し、いくつかの数学を実行しなければならないニューラルネットワークのオブジェクトを持っています。クラス?

私は3640オブジェクトの周りを扱っており、その上で(最高で)500回繰り返しているので、どんなマイクロ最適化でも大いに役立ちます。 $object['value']よりも$object->valueを行う方が必然的に速くなりますか?

編集:したがって、どちらも同じです。しかし、コンストラクタには少しオーバーヘッドがあると思いますか?いずれにせよ、私は自分の美しいクラスをダーティ配列と交換したいとは思わない:P

82
Louis

Quazzleのコードに基づいて、次のコード(5.4.16 Windows 64ビット)を実行しました。

<?php
class SomeClass {
    public $aaa;
    public $bbb;
    public $ccc;
    }

function p($i) {
  echo '<pre>';
  print_r($i);
  echo '</pre>';
}


$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = array();
    for ($j=0; $j<1000; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];            
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);

$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = new SomeClass();
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);

$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage(); 
for ($i=0; $i<1000; $i++) {
    $z = new stdClass();
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;          
    }
    $arraysOf[]=$z;
}
$fin=memory_get_usage();    
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);  
?>

そして、私は次の結果を得ました:

arrays: 1.8451430797577

memory: 460416

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 1.8294548988342

memory: 275696

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 2.2577090263367

memory: 483648

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

PHP 5.4の結論

  1. クラスは配列より高速です(ただし、わずかです)。
  2. stdClassは悪です。
  3. クラスは配列よりも少ないメモリを使用します。 (約30-40%減!!)

ps:注として、クラスが定義されていてもメンバーが定義されている場合、このクラスの使用は遅くなります。また、より多くのメモリを使用します。 明らかに秘密はメンバーを定義することです

更新

Php 5.4からphp 5.5(5.5.12 x86ウィンドウ)に更新しました。

arrays: 1.6465699672699

memory: 460400

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 1.8687851428986

memory: 363704

SplFixedArray Object
(
    [0] => aaa
    [1] => bbb
    [2] => aaabbb
)

arrays: 1.8554251194

memory: 275568

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 2.0101680755615

memory: 483656

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

PHP 5.5の結論

  1. 配列の場合、PHP 5.5はPHP 5.4よりも高速です。オブジェクトの場合、ほとんど同じです
  2. PHP 5.5と配列の最適化により、クラスは配列よりも遅くなります。
  3. stdClassは悪です。
  4. クラスは、配列よりも少ないメモリを使用します。 (約30〜40%減!!)。
  5. SplFixedArrayはクラスを使用するのと似ていますが、より多くのメモリを使用します。
62
magallanes

「プロファイリング」にこのコードを使用しました(1000インスタンス、1000.000読み取り/書き込み):

function p($i) {
  echo '<pre>';
  print_r($i);
  echo '</pre>';
}


$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
    $z = array();
    for ($j=0; $j<1000; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
}
echo '<p>arrays: '.(microtime(true) - $t0);
p($z);

$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
    $z = (object) null;
    for ($j=0; $j<1000; $j++) {
        $z->aaa = 'aaa';
        $z->bbb = 'bbb';
        $z->ccc = $z->aaa.$z->bbb;
    }
}
echo '<p>obj: '.(microtime(true) - $t0);
p($z);

echo '<p> phpversion '.phpversion();

このものをホストしているLINUXで出力します:

arrays: 1.1085488796234

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
obj: 1.2824709415436

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
phpversion 5.2.17

したがって、結論:objectsはPHP 5.2でも遅くなります。オブジェクトのoop機能が本当に必要でない限り、オブジェクトを使用しないでください。

9
Quazzle

私はmagallanesのコードをphp 7.0.9で使用しています:

arrays: 0.19802498817444

memory: 324672

Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.18602299690247

memory: 132376

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.1950249671936

memory: 348296

stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

そして、ユーザーphp 7.1.3:

arrays: 0.59932994842529
memory: 444920
Array
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 0.72895789146423
memory: 164512

SomeClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)

arrays: 0.61777496337891
memory: 484416
stdClass Object
(
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)                      
3
chariothy

$object->valueは、バックエンドが配列である可能性があるため、機能します。この場合、理論的に関数呼び出しが1つ少ないため、配列の使用が高速になります。ルックアップを実行するコストは、おそらく関数呼び出しに比べて莫大です。変数の場合、PHPのオブジェクトと配列は非常によく似た実装を持っているので、違いはほとんどありません。

最適化を検討している場合は、プロファイルを作成して、ほとんどの時間をどこで使用しているかを確認する必要があります。オブジェクトを配列に変更しても大きな違いはないと思います。

2
Yacoby

これは一種の古い投稿だと思うので、更新するつもりでした。 Zend CE 5.3.21で行われたコードと統計を以下に示します。情報全体をテストし、情報を保存して引き戻そうとしました。

V1:0.83秒かかります

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a[0];
  $b = $a[1];
}

function get_one() {
  return array(1,1);
}

V2:3.05秒かかります

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a->v;
  $b = $a->k;
}

function get_one() {
  $ret = new test();
  $ret->v = 1;
  $reb->k = 1;
  return $ret;
}

class test {
  public $v;
  public $k;
}

V3:1.98秒かかります(コンストラクターがパフォーマンスを改善することに注意してください)

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a->v;
  $b = $a->k;
}

function get_one() {
  return new test(1,1);
}

class test {
  public $v;
  public $k;
  public function __construct($v, $k) {
    $this->v = $v;
    $this->k = $k;
  }
}
2
Nir

そのようなマイクロパフォーマンス機能については、PHPソースコードをいつでも確認できます。

しかし、一見したところ、['value']の実行は速くなりません。PHP ['value']がどこにあるかを調べる必要があるからです。 (1)、それは保証されていません。Text-indexを使用すると、オーバーヘッドが増えます。

オブジェクトに、アクセスする必要がある変数が1つしか含まれていない場合、オブジェクトを使用するとオーバーヘッドが増えます。

1
Filip Ekberg

配列とクラスのパフォーマンスが同じである場合、ビジネスデータの格納/受け渡しに事前定義されたクラスのオブジェクトを使用すると、プログラムのロジックとコードが読みやすくなります。

今日、Eclipse、Netbeanのような現代のideで...(事前定義されたクラスの)オブジェクトがどの情報を伝えているかを知ることは非常に便利ですが、配列はそうではありません

例:配列あり

function registerCourse(array $student) {
    // Right here I don't know how a $student look like unless doing a print_r() or var_dump()
 ....
}

オブジェクト付き

class Studen {
    private $_name, $_age;
    public function getAge() {}
    public function getName() {}
    ..
}

function registerCourse(Studen $student) {
    // Right here I just Ctrl+Space $student or click "Student" and I know I can get name or age from it
    ...
}
0
trungnnh

雑誌のスクリプト@ PHP 7.3.5

  • SomeClass Objectは最速かつ最軽量です。
  • Array1.32x速度。 2.70xメモリ。
  • stdClass Object1.65x速度。 2.94x​​メモリ。

生の出力:

arrays: 0.064794063568115
memory: 444920
Array (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.048975944519043
memory: 164512
SomeClass Object (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
arrays: 0.081161022186279
memory: 484416
stdClass Object (
    [aaa] => aaa
    [bbb] => bbb
    [ccc] => aaabbb
)
0
Qcho