Was ändert sich mit PHP 5.3?

Seite 3: Garbage Collector

Inhaltsverzeichnis

Als Beispiel für die Vielzahl an Überarbeitungen "unter der Motorhaube" von PHP sei der neue Garbage Collector genannt. Er nutzt den in "Concurrent Cycle Collection in Reference Counted Systems" von IBM vorgestellten Algorithmus. Die PHP-Entwickler hatten ihn im Rahmen des Google Summer of Code 2007 implementiert.

Das Besondere an dem Garbage Collector ist, dass er Objektzyklen erkennt und auflöst. Dem Phänomen der Objektzyklen nähert man sich am besten über ein Beispiel.

    Node.php
<?php
class Node
{
protected $children = array();
protected $parent;

public function addChild(Node $node)
{
$node->setParent($this);
$this->children[] = $node;
}

public function setParent(Node $parent)
{
$this->parent = $parent;
}
}
?>

Das nachstehende Listing erzeugt ein Objekt der Klasse Node, die einen Knoten in einem Baum repräsentiert. Das Objekt erhält im nächsten Schritt über die Methode addChild() einen Kindknoten.

    <?php
require 'Node.php';

$root = new Node;
$root->addChild(new Node);
?>

PHP speichert beide Objekte intern (Abb. 1).

Abbildung 1 zeigt, wie PHP die beiden Objekte intern speichert:

  • Es gibt zwei Objekte der Klasse Node.
  • Eines der beiden Node-Objekte lässt sich über die Variable $root "von außen" ansprechen.
  • Die beiden Node-Objekte referenzieren sich gegenseitig.

Wenn die Variable $root nicht mehr definiert ist, weil man sie per unset() "gelöscht" hat oder weil die Ausführung den Scope verlässt, in dem man $root definiert hat, so ergibt sich mit den PHP-5.3-Vorgängern folgendes Resultat:

    <?php
require 'Node.php';

$root = new Node;
$root->addChild(new Node);
unset($root);
?>
  • Es gibt zwei Objekte der Klasse Node.
  • Die beiden Node-Objekte referenzieren sich gegenseitig.
  • Die Objekte in diesem Objektzyklus sind "von außen" nicht mehr zugreifbar.

Da sich die beiden Node-Objekte gegenseitig referenzieren, können die Referenzzähler nicht 0 werden und die Objekte eignen sich folglich nicht für das Garbage Collection, obwohl man sie nicht mehr verwendet beziehungsweise verwenden kann.

Der neue Garbage Collector in PHP 5.3 erkennt sowohl den Objektzyklus als auch die Tatsache, dass es keine Referenz von außen auf ein Objekt des Objektzyklus gibt. Die Objekte lassen sich so durch den Garbage Collector automatisch löschen.

Besonders bei lang laufenden PHP-Prozessen macht sich der neue Garbage Collector bemerkbar. Beispielsweise hat man bei der Ausführung der PHPUnit-Testsuite der eZ Components eine Verringerung des Speicherbedarfs von 1 GB mit PHP 5.2 auf 100 MB mit PHP 5.3 gemessen, die nur auf den Garbage Collector zurückzuführen ist. Ähnliche Verbesserungen meldet das Doctrine-Projekt, dessen Testsuite sich mit PHP 5.3 20 Prozent schneller und mit 30 Prozent geringerem Speicherbedarf ausführen lässt.

Die PHP-Entwickler haben einige weitere Überarbeitungen am PHP-Interpreter vorgenommen, die über die im Detail beschriebenen Verbesserungen des Garbage Collector hinaus gehen. Diese wirken sich sowohl auf die Ausführungsgeschwindigkeit als auch auf den Speicherverbrauch aus.

PHP-Benchmark zu unterschiedlichen PHP-5-Versionen (Abb. 3)

Wie aus dem Diagramm in Abbildung 3 abzulesen ist, führt PHP 5.3 den Zend/bench.php-Benchmark ungefähr 1,5-mal so schnell aus wie PHP 5.2 – und fast 4-mal so schnell wie PHP 5.0 (das ungefähr so schnell war wie PHP 4.4).

Zwar handelt es sich um einen "synthetischen" Benchmark, jedoch haben Migrationen von PHP 4 zu PHP 5 in der Praxis vergleichbare Verbesserungen bei realen Anwendungen gezeigt. So konnte beispielsweise die Foto-Plattform Flickr kürzlich die CPU-Last ihrer Server allein durch die Umstellung von PHP 4 auf PHP 5 um 20 Prozent reduzieren.