Heim  >  Artikel  >  Backend-Entwicklung  >  PHP-Garbage-Collection-Mechanismus – Leistungsüberlegungen

PHP-Garbage-Collection-Mechanismus – Leistungsüberlegungen

伊谢尔伦
伊谢尔伦Original
2016-11-22 09:57:491188Durchsuche

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 = &#39;3.1415962654&#39;;
    }
    $baseMemory = memory_get_usage();
    for ( $i = 0; $i <= 100000; $i++ )
    {
        $a = new Foo;
        $a->self = $a;
        if ( $i % 500 === 0 )
        {
            echo sprintf( &#39;%8d: &#39;, $i ), memory_get_usage() - $baseMemory, "\n";
        }
    }
?>

PHP-Garbage-Collection-Mechanismus – Leistungsüberlegungen

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 = &#39;3.1415962654&#39;;
    }
    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.


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn