Signatur
Beschreibung
gc_collect_cycles() löst manuell einen Durchlauf des zyklischen Garbage Collectors aus. Normalerweise wird der Garbage Collector von PHP automatisch gestartet, wenn der interne Puffer für verdächtige Wurzel-Referenzen voll läuft (standardmäßig nach 10.000 Einträgen). Mit dieser Funktion lässt sich dieser Vorgang gezielt zu einem selbst gewählten Zeitpunkt anstoßen.
Zirkuläre Referenzen entstehen, wenn Objekte oder Arrays wechselseitig aufeinander verweisen (z. B. Eltern–Kind-Beziehungen), sodass der normale Referenzzähler niemals auf null fällt. Ohne den zyklischen Garbage Collector würde der belegte Speicher nie freigegeben und zu einem Speicherleck führen.
Die Funktion ist besonders nützlich in lang laufenden Skripten, Daemon-Prozessen oder CLI-Applikationen, bei denen in Schleifen viele Objekte mit gegenseitigen Referenzen erzeugt und verworfen werden. Durch den gezielten Aufruf kann man Speicherspitzen kontrollieren, ohne auf den automatischen Auslöser warten zu müssen.
Voraussetzung ist, dass die Garbage Collection aktiv ist (gc_enable() bzw. zend.enable_gc = On in der php.ini). Ist sie deaktiviert, führt gc_collect_cycles() zwar einen Lauf durch, sammelt aber praktisch nichts ein.
Rückgabewert
0 bedeutet, dass keine zirkulären Referenzen gefunden wurden.Beispiele
Zirkuläre Referenzen manuell einsammeln und Speicher prüfen
<?php
class Node {
public ?Node $child = null;
public ?Node $parent = null;
}
// Zirkuläre Referenz erzeugen
$a = new Node();
$b = new Node();
$a->child = $b;
$b->parent = $a;
// Referenzen aufheben, aber Zyklus bleibt im Speicher
unset($a, $b);
$vorher = memory_get_usage();
$gesammelt = gc_collect_cycles();
$nachher = memory_get_usage();
echo "Gesammelte Zyklen: {$gesammelt}\n";
echo "Speicher vorher: {$vorher} Bytes\n";
echo "Speicher nachher: {$nachher} Bytes\n";
echo "Freigegeben: " . ($vorher - $nachher) . " Bytes\n";
Regelmäßige GC-Aufrufe in einer langen Verarbeitungsschleife
<?php
gc_enable(); // Sicherstellen, dass GC aktiv ist
class Job {
public ?Job $next = null;
public array $data = [];
}
$gesamtGesammelt = 0;
for ($i = 0; $i < 10000; $i++) {
$job1 = new Job();
$job2 = new Job();
$job1->next = $job2; // zirkuläre Referenz
$job2->next = $job1;
$job1->data = range(1, 100);
unset($job1, $job2);
// Alle 500 Iterationen GC manuell anstoßen
if ($i % 500 === 499) {
$gesamtGesammelt += gc_collect_cycles();
}
}
echo "Insgesamt gesammelte Zyklen: {$gesamtGesammelt}\n";
// Wichtig · Fallstricke
Performance: Ein GC-Lauf ist nicht kostenlos. In sehr engen, zeitkritischen Schleifen sollte man die Aufrufhäufigkeit abwägen. Zu häufige Aufrufe können die Laufzeit messbar erhöhen. Als Faustregel empfiehlt es sich, gc_collect_cycles() nur periodisch (z. B. alle N Iterationen) aufzurufen.
Zusammenspiel mit gc_disable(): Wenn der automatische GC per gc_disable() oder zend.enable_gc = Off abgeschaltet wurde, führt gc_collect_cycles() dennoch einen einmaligen Lauf durch. Das ist in manchen Szenarien nützlich, um den GC zu einem selbst kontrollierten Zeitpunkt gezielt zu aktivieren, ohne die automatische Auslösung zu erlauben.
Circular-Reference-Erkennung: PHP erkennt nur Zyklen in Objekt- und Array-Strukturen. Ressourcen und skalare Werte werden nicht berücksichtigt.