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
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
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
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
)
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.
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
)
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.
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;
}
}
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.
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
...
}
script de magallanes @ PHP 7.3.5
SomeClass Object
est le plus rapide et le plus léger.Array
1,32x vitesse. 2.70x mémoire.stdClass Object
1,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
)