Can someone please explain under what circumstances gc_collect_cycles function can be useful? Should it be called before a substantial memory utilization is about to take place?
The garbage collector is triggered whenever 10,000 possible cyclic objects or arrays are currently in memory, and one of them falls out of scope. The collector is enabled by default in every request. And this is, generally a good thing.
The purpose of a garbage collector is to monitor memory allocation and determine when a block of allocated memory is no longer needed and reclaim it.
The garbage collector takes roots and “marks” (remembers) them. Then it visits and “marks” all references from them. Then it visits marked objects and marks their references. All visited objects are remembered, so as not to visit the same object twice in the future.
PHP has a combination of garbage collection and reference counting. The latter is the main mode of managing memory, with the garbage collector picking up the pieces that the ref counter misses (circular references).
PHP has "Garbage Collector" enabled by default. It is used to free memory used by "garbage". gc_collect_cycles()
forces collection of any existing garbage cycles. It returns number of collected (freed) cycles (objects, variable values ...). Enabled Garbage Collector calls this function internally from time to time to free resources. In most cases PHP script lives very short time. In this case all garbage will be destroyed in the end of work without any garbage collection.
Sometimes it's needed to manage GC manually:
gc_disable()
can speed up some long operations, but also results in some memory overheads.gc_collect_cycles()
could be used to specify the right moments of GC.Another one reason to use gc_collect_cycles()
- debugging. Assume, you want to know what is the memory consumption of some block of code with memory_get_usage()
. You need to disable GC first, elsewhere you'll get wrong results. After that you want to separate the time consumed by GC and by your application. So call gc_collect_cycles()
and measure timings/memory before and after.
Little example:
class A { public $ref; public $name; public function __construct($name) { $this->name = $name; echo($this->name.'->__construct();'.PHP_EOL); } public function __destruct() { echo($this->name.'->__destruct();'.PHP_EOL); } } gc_disable(); $a1 = new A('$a1'); $a2 = new A('$a2'); $a1->ref = $a2; $a2->ref = $a1; $b = new A('$b'); $b->ref = $a1; echo('$a1 = $a2 = $b = NULL;'.PHP_EOL); $a1 = $a2 = $b = NULL; echo('gc_collect_cycles();'.PHP_EOL); echo('// removed cycles: '.gc_collect_cycles().PHP_EOL); echo('exit();'.PHP_EOL);
Will output:
$a1->__construct(); $a2->__construct(); $b->__construct(); $a1 = $a2 => $b = NULL; $b->__destruct(); gc_collect_cycles(); $a2->__destruct(); $a1->__destruct(); // removed cycles: 4
This means that only $b
was destroyed when it was asked. Other $a1
and $a2
has cyclic references, and it's name
properties also consume memory. Two objects + two strings = 4 (removed by gc_collect_cycles()
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With