Recycling kann einen leichten Einfluss auf die Leistung haben, dies gilt jedoch nur beim Vergleich von PHP 5.2 mit PHP 5.3. Obwohl die Protokollierung in PHP 5.2 langsamer sein kann als gar keine Protokollierung, reduzieren andere Änderungen an der PHP-Laufzeit in PHP 5.3 diese Leistungseinbußen.
Es gibt zwei Hauptbereiche, die einen Einfluss auf die Leistung haben. Das erste ist die Einsparung von Speicherplatz und das andere die Erhöhung der Ausführungszeit (Laufzeitverzögerung), wenn der Garbage-Collection-Mechanismus eine Speicherbereinigung durchführt. Wir werden uns beide Bereiche ansehen.
Speicherplatzeinsparungen
Der Hauptgrund für die Implementierung eines Garbage-Collection-Mechanismus besteht darin, Speicherbedarf zu sparen, indem zirkulär referenzierte Variablen bereinigt werden, sobald die Voraussetzungen erfüllt sind. Bei der PHP-Ausführung wird die Garbage Collection durchgeführt, sobald der Root-Puffer voll ist oder die Funktion gc_collect_cycles() aufgerufen wird. In der folgenden Abbildung wird die Speichernutzung der folgenden Skripte in PHP 5.2- und PHP 5.3-Umgebungen gezeigt, mit Ausnahme des Grundspeichers, der von PHP selbst beim Start des Skripts belegt wird.
Beispiel #1 Speichernutzungsbeispiel
<?php class Foo { public $var = '3.1415962654'; } $baseMemory = memory_get_usage(); for ( $i = 0; $i <= 100000; $i++ ) { $a = new Foo; $a->self = $a; if ( $i % 500 === 0 ) { echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n"; } } ?>
In diesem sehr theoretischen Beispiel erstellen wir ein Objekt erhalten, und eine Eigenschaft in diesem Objekt wird so festgelegt, dass sie auf das Objekt selbst verweist. Ein typischer Speicherverlust tritt auf, wenn die Variablen im Skript während der nächsten Iteration der Schleife erneut kopiert werden. In diesem Beispiel sind zwei Variablencontainer verloren gegangen (der Objektcontainer und der Attributcontainer), es kann jedoch nur ein möglicher Stamm gefunden werden: die Variable, die nicht gesetzt wurde. Wenn nach 10.000 Wiederholungen (was insgesamt 10.000 mögliche Roots ergibt) der Root-Puffer voll ist, wird ein Garbage-Collection-Mechanismus ausgeführt und der mit den möglichen Roots verknüpfte Speicher freigegeben. Dies lässt sich leicht im Sägezahn-Speichernutzungsdiagramm von PHP 5.3 erkennen. Nach jeder Ausführung von 10.000 Wiederholungen wird eine Speicherbereinigung durchgeführt und zugehörige wiederverwendete Referenzvariablen werden freigegeben. Da die durchgesickerte Datenstruktur in diesem Beispiel sehr einfach ist, muss der Garbage-Collection-Mechanismus selbst nicht viel Arbeit leisten. Aus diesem Diagramm können Sie ersehen, dass der maximale Speicherbedarf von PHP 5.3 etwa 9 MB beträgt, während der Speicherbedarf von PHP 5.2 ständig zunimmt.
Laufzeitverlangsamungen
Der zweite Bereich, in dem sich die Garbage Collection auf die Leistung auswirkt, ist die Zeit, die benötigt wird, um verlorenen Speicher freizugeben. Um zu sehen, wie lange dies dauert, haben wir das obige Skript leicht geändert, um mehr Wiederholungen zu haben und die Speichernutzungsberechnung in der Schleife zu entfernen. Der zweite Skriptcode lautet wie folgt:
Beispiel #2 GC-Leistungseinflüsse
<?php class Foo { public $var = '3.1415962654'; } for ( $i = 0; $i <= 1000000; $i++ ) { $a = new Foo; $a->self = $a; } echo memory_get_peak_usage(), "\n"; ?>
Wir werden dieses Skript zweimal ausführen, einmal, wenn die Garbage Collection durch die Konfiguration von zend.enable_gc aktiviert ist, und einmal, wenn sie deaktiviert ist.
Beispiel Nr. 3: Ausführen des obigen Skripts
time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php # and time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php
Auf meinem Computer dauerte der erste Befehl etwa 10,7 Sekunden, während der zweite Befehl 11,4 Sekunden dauerte. Zeit um 7 % erhöht. Allerdings wurde die Spitzenspeichernutzung beim Ausführen dieses Skripts um 98 % von 931 MB auf 10 MB reduziert. Dieser Benchmark ist nicht sehr wissenschaftlich oder repräsentativ für reale Anwendungsdaten, zeigt aber die Vorteile der Garbage Collection im Hinblick auf die Speichernutzung. Die gute Nachricht ist, dass bei diesem Skript die Speichereinsparungen größer sind, wenn mehr zirkuläre Referenzvariablen in der Ausführung auftreten, und die prozentuale Zeitverlängerung jedes Mal 7 % beträgt.
PHP-interne GC-Statistiken
In PHP können Sie weitere Informationen über die Funktionsweise des Garbage-Collection-Mechanismus anzeigen. Um diese Informationen anzuzeigen, müssen Sie PHP jedoch zunächst neu kompilieren, um den Benchmark- und Datenerfassungscode verfügbar zu machen. Sie müssen die Umgebungsvariable CFLAGS auf -DGC_BENCH=1 setzen, bevor Sie ./configure wie gewünscht ausführen. Die folgende Befehlszeichenfolge bewirkt genau das:
Beispiel #4 PHP neu kompilieren, um GC-Benchmarking zu ermöglichen
export CFLAGS=-DGC_BENCH=1 ./config.nice make clean make
Wenn Sie den obigen Beispielcode mit der neu kompilierten PHP-Binärdatei After PHP erneut ausführen Wenn die Ausführung beendet ist, werden die folgenden Informationen angezeigt:
Beispiel Nr. 5 GC-Statistiken
GC Statistics ------------- Runs: 110 Collected: 2072204 Root buffer length: 0 Root buffer peak: 10000 Possible Remove from Marked Root Buffered buffer grey -------- -------- ----------- ------ ZVAL 7175487 1491291 1241690 3611871 ZOBJ 28506264 1527980 677581 1025731
Die Hauptinformationsstatistiken befinden sich im ersten Block. Sie können sehen, dass der Garbage-Collection-Mechanismus 110 Mal ausgeführt wurde und in diesen 110 Durchläufen insgesamt mehr als 2 Millionen Speicherzuweisungen freigegeben wurden. Solange der Garbage-Collection-Mechanismus mindestens einmal ausgeführt wird, beträgt der Root-Puffer-Peak (Root-Buffer-Peak) immer 10000.
Fazit
Normalerweise funktioniert der Garbage-Collection-Mechanismus in PHP nur, wenn der Der Zyklussammlungsalgorithmus ist Während der Laufzeit erhöht sich der Zeitverbrauch. Bei normalen (kleineren) Skripten sollte es jedoch keinerlei Auswirkungen auf die Leistung geben.
Bei normalen Skripten mit laufenden Recycling-Mechanismen ermöglichen die Speichereinsparungen jedoch die gleichzeitige Ausführung mehrerer solcher Skripte auf Ihrem Server. Weil der insgesamt verwendete Speicher die Obergrenze nicht erreicht hat.
Dieser Vorteil ist besonders deutlich bei Skripten mit langer Laufzeit, wie z. B. Testsuiten oder Daemon-Skripten mit langer Laufzeit. Gleichzeitig sollte der neue Garbage-Collection-Mechanismus für PHP-GTK-Anwendungen, die typischerweise länger laufen als Webskripte, die lange vertretene Ansicht, dass Speicherlecks schwer zu beheben sind, stark ändern.