web-dev-qa-db-fra.com

PHP Objects vs Arrays - Comparaison des performances lors de l'itération

J'ai une énorme quantité d'objets PHP pour un réseau de neurones pour lesquels je dois répéter et effectuer des calculs. Je me demandais s'il serait préférable d'utiliser un tableau associatif sur des instances de Des classes?

J'ai affaire à environ 3640 objets et itération autour de 500 fois (au mieux) en plus de cela, donc toute micro-optimisation aide beaucoup. Serait-il inévitablement plus rapide de faire $object['value'] que $object->value?

Edit: Ils sont donc tous les deux identiques. Mais je suppose qu'il y aurait un peu de frais généraux pour le constructeur? Quoi qu'il en soit, je ne pense pas que je veux échanger mes belles classes contre des tableaux sales: P

82
Louis

Basé sur le code de Quazzle, j'ai exécuté le code suivant (5.4.16 windows 64bits):

<?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);  
?>

Et j'ai obtenu le résultat suivant:

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
)

Conclusion pour PHP 5.4

  1. La classe est plus rapide que les tableaux (mais marginalement).
  2. stdClass est mauvais.
  3. La classe utilise moins de mémoire que les tableaux. (environ 30 à 40% de moins !!)

ps: comme une note, si la classe est définie mais les membres alors, l'utilisation de cette classe est plus lente. Il utilise également plus de mémoire. Apparemment, le secret est de définir les membres

Mise à jour

J'ai mis à jour de php 5.4 à php 5.5 (5.5.12 x86 windows).

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
)

Conclusion pour PHP 5.5

  1. Pour les tableaux, PHP 5.5 est plus rapide que PHP 5.4, pour l'objet, il est à peu près le même
  2. La classe est plus lente que les tableaux grâce à l'optimisation de PHP 5.5 et des tableaux.
  3. stdClass est mauvais.
  4. La classe utilise toujours moins de mémoire que les tableaux. (environ 30-40% de moins !!).
  5. SplFixedArray est similaire à l'utilisation d'une classe, mais il utilise plus de mémoire.
62
magallanes

J'ai utilisé ce code pour le "profilage" (1000 instances, 1000.000 lectures/écritures):

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();

Il sort dans mon LINUX hébergeant ce genre de choses:

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

donc en conclusion: les objets sont plus lents même sur PHP 5.2. N'utilisez pas d'objets sauf si vous avez vraiment besoin de leurs fonctionnalités oop.

9
Quazzle

J'utilise le code de magallanes sous 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
)

Et l'utilisateur 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

Vous ne nous avez pas montré le code pour savoir comment $object->value fonctionne, car il se pourrait que le backend soit un tableau auquel cas théoriquement utiliser un tableau serait plus rapide car il implique un appel de fonction en moins. Le coût de la recherche sera probablement énorme par rapport à l'appel de fonction. S'il s'agit d'une variable, il y aura très peu de différence car les objets et les tableaux dans PHP ont une implémentation très similaire.

Si vous cherchez des optimisations, vous devrez profiler pour vérifier où la majorité du temps est utilisée. Je soupçonne que le changement d'objets en tableaux ne fera aucune différence majeure.

2
Yacoby

Je vois que c'est une sorte de vieux post alors j'ai pensé que je le mettrais à jour. voici mes codes et statistiques, fait sur Zend CE 5.3.21 J'ai essayé de tester le tout, de stocker des informations et de les retirer.

V1: prend 0,83 s

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

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

V2: prend 3,05 s

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: prend 1,98 sec (notez que le constructeur améliore les performances)

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

Vous pouvez toujours vérifier le code source PHP pour des fonctionnalités de micro-performances comme ça.

Mais à première vue, ne pas faire ['value'] ne sera pas plus rapide car PHP doit faire une recherche pour savoir où trouver ['value'] même si une recherche de table de hachage doit être O (1), ce n'est pas garanti. Il y a plus de surcharge lorsque vous utilisez Text-index.

Si l'objet ne contient qu'une seule variable à laquelle vous devez accéder, qui est une valeur, il y a plus de surcharge dans l'utilisation d'un objet.

1
Filip Ekberg

Si les tableaux et les classes ont les mêmes performances, je pense que l'utilisation d'objets de classes prédéfinies pour stocker/transmettre des données métier rendrait notre programme plus logique et le code plus lisible.

Aujourd'hui, avec des idées modernes comme Eclipse, Netbean ... il est très pratique de savoir quelles informations un objet (de classe prédéfinie) transporte mais les tableaux ne le sont pas

Par exemple: avec tableau

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

Avec objet

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

script de magallanes @ PHP 7.3.5

  • SomeClass Object est le plus rapide et le plus léger.
  • Array1,32x vitesse. 2.70x mémoire.
  • stdClass Object1,65x vitesse. 2.94x mémoire.

Sortie brute:

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