am 5. September 2008
Da ich immer mal wieder verwunderte PHP Programmierer höre, die sich wundern warum PHP keinen Speicher freigibt, sobald ich mal unset auf eine Variable aufrufe. Das liegt natürlich am garbage collector. Dieser Müllschlucker sucht sich von zeit zu Zeit alle Variablen raus, zu denen es keine Referenz meht gibt und schmeißt diese weg. Dabei muss PHP nur die Anzahl der Referenzen auf ein Objekt festhalten.
$a= new A; // 1 Referenz
$b = $a; // 2 Referenzen
unset( $a ); // 1 Referenz
unset( $b); // 0 Referenzen
Sobald wir bei 0 Referenzen angekommen sind kann der Garbage Collection loslegen. Beim nächsten Lauf würde er also das Objekt aus dem Speicher entfernen. Dieser Durchlauf muss nicht zwingender Weise direkt nach dem unset passieren. Klingt ja eigentlich recht einfach. Schauen wir uns doch einfach mal einen ein wenig komplexeren Fall an.
$a->b = $b;
$b->a = $a;
Diese zyklischen Referenzen machen dem Collector schon eher Probleme. Da beide Objekte sich gegenseitig referenzieren, kann hier das Zählen nicht mehr klappen. Und hier versagt der PHP Garbage Collector wirklich. Alle Versionen unter PHP 5.3 schaffen es nicht diesen Zyklus aufzulösen und den Speicher frei zu kriegen. Ein Speicherfresser kann so also sehr einfach programmiert werden, da dieses Konstrukt ja immer mal wieder vorkommen kann. Aber das ist wieder so eine typische PHP Sache. Wir haben ein Standardproblem und schaffen es nicht eine Standardlösung zu implementieren.
Wie ich auf der Froscon im Vortrag von Johannes Schlüter erfahren habe, haben die Entwickler von PHP es endlich geschafft dieses Problem zu lösen. Johannes hat aber immer dazu gesagt, dass man diesen Collector ohne Probleme abschalten kann. Das läßt einen natürlich vermuten, dass die neue Methode zyklischen Referenzen zu finden nicht besonders ressourcenschonend implementiert wurde. Aber der Weg den sie eingeschlagen habe ist auf jedenfall der richtige.