What is PHP Garbage Collection?
PHP garbage collection (GC) is the built‑in mechanism that automatically reclaims memory occupied by variables and objects that are no longer reachable by the running script. By freeing unused memory, GC helps prevent memory leaks, improves performance, and keeps long‑running PHP processes (like workers, daemons, or scripts executed via php -d) stable.
Why Does PHP Need Garbage Collection?
PHP scripts often create thousands of objects, arrays, and resources during a single request. Without an automated way to clean up memory, developers would have to manually unset() every variable, which is error‑prone and inefficient. Garbage collection solves this by:
- Detecting objects that are no longer referenced.
- Breaking reference cycles that traditional reference counting cannot resolve.
- Releasing memory back to the PHP engine for reuse.
How Does PHP Garbage Collection Work?
Modern PHP (since version 5.3) uses a hybrid approach that combines reference counting with a cyclic garbage collector. The process can be broken down into three main steps:
1. Reference Counting
Every zval (the internal container for a value) maintains a refcount. When a variable is assigned or passed by value, the count increases; when it goes out of scope or is unset(), the count decreases. When the count reaches zero, the memory is immediately freed.
2. Detecting Reference Cycles
A reference cycle occurs when two or more objects reference each other, preventing their refcounts from ever reaching zero. Example:
class Node {
public $next;
}
$a = new Node();
$b = new Node();
$a->next = $b;
$b->next = $a; // creates a cycle
The cyclic GC periodically scans for such structures, marks them, and then frees them if they are unreachable from the root symbol table.
3. Collection Phases
- Mark Phase: Traverses all reachable objects from the root set and marks them.
- Sweep Phase: Unmarks objects that are not reachable and frees their memory.
The collector runs based on a configurable threshold (controlled by gc_collect_cycles() and the zend.enable_gc INI setting).
Configuring PHP Garbage Collection
PHP provides several INI directives to fine‑tune GC behavior:
zend.enable_gc(default1) – Enables or disables the cyclic collector.zend.gc_probabilityandzend.gc_divisor– Define the probability that GC runs on each request (default 1/10000).zend.gc_memthreshold– Memory threshold (in bytes) after which GC may be triggered.
Best Practices for Developers
While PHP handles most memory cleanup automatically, following these practices can further reduce memory usage:
- Unset large variables when they are no longer needed, especially in long‑running scripts.
- Avoid unnecessary
globalreferences that can create hidden cycles. - Prefer
weakref(available via theWeakReferenceclass) for caching objects that should not prevent GC. - Monitor memory usage with
memory_get_usage()andmemory_get_peak_usage(). - When using extensions or custom C code, ensure they correctly implement reference counting.
Common Questions (FAQ)
Does disabling GC improve performance?
Disabling GC can reduce overhead for short‑lived scripts, but it risks memory leaks in long‑running processes. It’s generally recommended to keep GC enabled and only adjust thresholds if profiling shows a bottleneck.
How can I manually trigger garbage collection?
Use gc_collect_cycles(); to force an immediate collection cycle. This is useful in loops that create many temporary objects.
Is GC available in all PHP versions?
Reference counting has existed since early PHP versions, but the cyclic garbage collector was introduced in PHP 5.3 and has been improved in later releases (PHP 7.x and PHP 8.x). Always run a recent, supported version for the best GC performance.
What is the impact of GC on memory fragmentation?
GC helps reduce fragmentation by freeing whole objects and their associated memory blocks, but fragmentation can still occur at the allocator level. Using gc_memthreshold to trigger GC earlier can mitigate this.