PHP Objects vs Arrays - Leistungsvergleich beim Iterieren


87

Ich habe eine große Anzahl von PHP-Objekten für ein neuronales Netzwerk, für die ich iterieren und einige Berechnungen durchführen muss. Ich habe mich gefragt, ob ich besser dran wäre, ein assoziatives Array für Klasseninstanzen zu verwenden.

Ich beschäftige mich mit 3640Objekten und iteriere herum500 (bestenfalls) Zeiten, sodass jede Mikrooptimierung sehr hilfreich ist. Wäre es unweigerlich schneller $object['value']als $object->value?

Edit: Also sind beide gleich. Aber ich denke, es würde ein wenig Aufwand für den Konstrukteur geben? So oder so glaube ich nicht, dass ich meine schönen Klassen gegen schmutzige Arrays eintauschen möchte: P.

Antworten:


63

Basierend auf dem Code von Quazzle habe ich den nächsten Code ausgeführt (5.4.16 Windows 64bit):

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

Und ich habe das nächste Ergebnis erhalten:

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
)

Schlussfolgerung für PHP 5.4

  1. Klasse ist schneller als Arrays (aber nur am Rande).
  2. stdClass ist böse.
  3. Die Klasse benötigt weniger Speicher als Arrays. (ca. 30-40% weniger !!)

ps: Wenn die Klasse definiert ist, aber die Mitglieder, ist die Verwendung dieser Klasse langsamer. Es verwendet auch mehr Speicher. Anscheinend besteht das Geheimnis darin, die Mitglieder zu definieren

Aktualisieren

Ich habe von PHP 5.4 auf PHP 5.5 aktualisiert (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
)

Schlussfolgerung für PHP 5.5

  1. Für Arrays ist PHP 5.5 schneller als PHP 5.4, für Objekte ist es ziemlich gleich
  2. Dank der Optimierung von PHP 5.5 und Arrays ist die Klasse langsamer als Arrays.
  3. stdClass ist böse.
  4. Die Klasse benötigt immer noch weniger Speicher als Arrays. (ca. 30-40% weniger !!).
  5. SplFixedArray ähnelt der Verwendung einer Klasse, benötigt jedoch mehr Speicher.

Gut gemacht, mein Herr. Es wäre interessant, dies auf verschachtelte Arrays usw. auszudehnen. Interessante Websites für andere PHP-Leistungen: phpbench.com php-benchmark-script.com, aber ich finde es gut , dass Sie auch Speicher verwendet haben.
Heath N

2
Mit PHP7 wurde der Unterschied zwischen Arrays und Objekten signifikanter. Ihr Skript zeigt einen Unterschied von 30% Laufzeit und 60% Speicher. Das ist nur meine Maschine, aber als Faustregel: Verwenden Sie keine Arrays als Strukturen. Verwenden Sie stattdessen Objekte :)
KingCrunch

Unterscheiden sich Objekte in diesem Fall von Klassen?
Matt G

Setzen Sie ein Lesezeichen in der Hoffnung auf ein PHP7-Update. Und das vielleicht das kommende PHP8, falls zutreffend. @magallanes
s3c

9

Ich habe diesen Code für die "Profilerstellung" verwendet (1000 Instanzen, 1000.000 Lese- / Schreibvorgänge):

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

Es gibt in meinem LINUX Folgendes aus:

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

Fazit: Objekte sind auch unter PHP 5.2 langsamer. Verwenden Sie keine Objekte, es sei denn, Sie benötigen deren oop-Funktionen wirklich.


7
vom Benutzer levans stackoverflow.com/users/1473035/levans : Ich habe dies mit 5.3.8 ausgeführt und Objekte waren langsamer, 0.51839280128479 für Arrays gegenüber 0.85355806350708 für Objekte. Ich habe es auch auf 5.4.13 ausgeführt und die gegenteiligen Ergebnisse erhalten, wahrscheinlich aufgrund der Klassenoptimierungen in 5.4, 0.6256799697876 für Arrays gegenüber 0.43650078773499. Es sieht also so aus, als hätte sich der Spieß umgedreht und Objekte sind jetzt der richtige Weg.
Jean-Bernard Pellerin

1
Gute Antwort, ich habe gerade auf XAMPP (Apache) getestet und die folgenden Ergebnisse erhalten: Arrays: 0.5174868106842 Array ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) obj: 0.72189617156982 stdClass Object ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) phpversion 5.4.19
ilhnctn

1
Ich lief auch am 5.4.13, bekam aber das Gegenteil von Jean-Bernard Pellerin: Arrays: 0.5020840167999 Objekte: 1.0378720760345 Also würde ich mich noch nicht auf Objekte festlegen.
Simontemplar

Ich habe einige Änderungen am Code vorgenommen und Class ist schneller als Arrays für PHP 5.4 (5.4.16 32-Bit-Windows). Ich habe eine neue Antwort gegeben, die den Grund erklärt.
Magallanes

PHP 5.5.11 Ergebnisse: Arrays: 0.17430, Objekte: 0.24183
Lex

3

Ich benutze den Code von Magallanes unter 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
)

Und Benutzer 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
)                      

1
Und vergessen Sie nicht, dass stdClass echte Ziffernschlüssel verwenden kann. ['1' => 1] wird als [1 => 1] gespeichert, aber wir können $a=new stdClass(); $a->{1} = 1; $b=(array)$a;get real ['1' => 1] verwenden.
Chariothy

2
Fazit: Arrays sind 18% schneller, verbrauchen aber 2,7-mal so viel Speicher.
Jchook

3

magallanes 'Skript @ PHP 7.3.5

  • SomeClass Object ist am schnellsten und am leichtesten.
  • Array 1,32x Geschwindigkeit. 2,70x Speicher.
  • stdClass Object 1,65x Geschwindigkeit. 2,94x Speicher.

Rohleistung:

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
)

3

Für alle, die sich noch für diese Frage interessieren :) Ich habe Quazzle-Code auf PHP 7.1 Ubuntu x64 ausgeführt und diese Antwort erhalten:

arrays: 0.24848890304565

memory: 444920

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

memory: 164512

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

memory: 484416

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

Fazit

Array nimmt 4 (!) Den Speicher als Klassenobjekt.
Klassenobjekt etwas schneller.
stdClass immer noch böse © magallanes :)


2

Sie haben uns den Code für die Funktionsweise nicht gezeigt $object->value, da es sich bei dem Backend möglicherweise um ein Array handelt. In diesem Fall handelt es sich theoretisch um ein Array Verwendung eines Arrays schneller, da ein Funktionsaufruf weniger erforderlich ist. Die Kosten für die Suche werden im Vergleich zum Funktionsaufruf wahrscheinlich enorm sein. Wenn es sich um eine Variable handelt, wird es kaum Unterschiede geben, da Objekte und Arrays in PHP eine sehr ähnliche Implementierung haben.

Wenn Sie Optimierungen in Betracht ziehen, müssen Sie ein Profil erstellen, um zu überprüfen, wo die meiste Zeit verwendet wird. Ich vermute, dass das Ändern von Objekten in Arrays keinen großen Unterschied macht.


Ich nahm an, dass value eine öffentliche Variable ist, daher definitiv O (1), während die Hash-Suche dies möglicherweise nicht ist.
Filip Ekberg

2

Ich sehe, dass dies eine Art alter Beitrag ist, also dachte ich, ich werde ihn aktualisieren. Hier sind meine Codes und Statistiken, die in Zend CE 5.3.21 erstellt wurden. Ich habe versucht, das Ganze zu testen, Informationen zu speichern und sie zurückzuziehen.

V1: dauert 0,83 Sekunden

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

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

V2: dauert 3,05 Sek

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: dauert 1,98 Sekunden (beachten Sie, dass der Konstruktor die Leistung verbessert)

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;
  }
}

1

Sie können den PHP-Quellcode jederzeit auf solche Leistungsmerkmale überprüfen.

Aber auf den ersten Blick wird kein ['Wert'] schneller sein, da PHP eine Suche durchführen muss, wo ['Wert'] zu finden ist, obwohl eine Hashtabellen-Suche O (1) sein sollte, was nicht garantiert ist. Es gibt mehr Overhead, wenn Sie Text-Index verwenden.

Wenn das Objekt nur 1 Variablen enthält, auf die Sie zugreifen müssen, was Wert ist, ist die Verwendung eines Objekts mit mehr Aufwand verbunden.


Und wo werden Ihrer Meinung nach Immobilien nachgeschlagen? Sie sind auch in einer Hash-Tabelle ... (obwohl dies nur im Kofferraum mehr oder weniger zutrifft).
Artefacto

0

Wenn Arrays und Klassen dieselbe Leistung haben, würde die Verwendung von Objekten vordefinierter Klassen zum Speichern / Übergeben von Geschäftsdaten unser Programm logischer und die Lesbarkeit des Codes verbessern.

Mit modernen Ideen wie Eclipse, Netbean ... ist es heute sehr praktisch zu wissen, welche Informationen ein Objekt (einer vordefinierten Klasse) enthält, Arrays jedoch nicht

ZB: Mit Array

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

Mit Objekt

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
    ...
}

Dies widerspricht den anderen nachgewiesenen Antworten und hat keinen Beweis. Das ist also eher ein ideologischer Glaube als eine tatsächliche Antwort.
Scones
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.