logger = new \PrefixedLogger($logger, "Cyclic Garbage Collector"); $this->timings = new TimingsHandler("Cyclic Garbage Collector", $parentTimings); } private function adjustGcThreshold(int $cyclesCollected, int $rootsAfterGC) : void{ //TODO Very simple heuristic for dynamic GC buffer resizing: //If there are "too few" collections, increase the collection threshold //by a fixed step //Adapted from zend_gc.c/gc_adjust_threshold() as of PHP 8.3.14 if($cyclesCollected < self::GC_THRESHOLD_TRIGGER || $rootsAfterGC >= $this->threshold){ $this->threshold = min(self::GC_THRESHOLD_MAX, $this->threshold + self::GC_THRESHOLD_STEP); }elseif($this->threshold > self::GC_THRESHOLD_DEFAULT){ $this->threshold = max(self::GC_THRESHOLD_DEFAULT, $this->threshold - self::GC_THRESHOLD_STEP); } } public function getThreshold() : int{ return $this->threshold; } public function getCollectionTimeTotalNs() : int{ return $this->collectionTimeTotalNs; } public function maybeCollectCycles() : int{ $rootsBefore = gc_status()["roots"]; if($rootsBefore < $this->threshold){ return 0; } $this->timings->startTiming(); $start = hrtime(true); $cycles = gc_collect_cycles(); $end = hrtime(true); $rootsAfter = gc_status()["roots"]; $this->adjustGcThreshold($cycles, $rootsAfter); $this->timings->stopTiming(); $time = $end - $start; $this->collectionTimeTotalNs += $time; $this->logger->debug("gc_collect_cycles: " . number_format($time) . " ns ($rootsBefore -> $rootsAfter roots, $cycles cycles collected) - total GC time: " . number_format($this->collectionTimeTotalNs) . " ns"); return $cycles; } }