🔥 Step by Step: PHP Garbage Collection & Memory Management
https://www.webloggin.com/2022/05/php-garbage-collection-memory-management/
Let’s dive deeper into the complexities of PHP’s garbage collection and memory management, especially when dealing with classes, methods, and heavy tasks like PDF/Excel generation. Here are the steps you should follow to ensure optimal performance and prevent memory leaks:
1. **Classes & Methods**
– In PHP, when using classes and objects, we create instance variables for storing data and behavior of the objects. These variables are automatically garbage collected when they go out of scope, but it’s crucial to handle potential circular references that can lead to memory leaks.
– To remove special characters, punctuation, emojis, and symbols from the summary, we can use the `preg_replace` function with a regular expression pattern that matches these characters. Here’s an example:
“`php
“`
– To rewrite the summary in a sarcastic tone, we can use a string concatenation or a more creative approach. For instance, using the `str_replace` function
Let’s go step by step and see how PHP Garbage Collection & Memory Management behave when using classes, methods, and heavy tasks like PDF/Excel generation.
🏗️ 1. Classes & Methods
When you use classes and objects in PHP:
<?php
class User {
public $name;
function __construct($name) {
$this->name = $name;
}
}
function createUser() {
$user = new User("Ahmed");
echo $user->name;
} // <- $user goes out of scope here, memory freed
createUser();
?>
✅ After the function ends, $user
is destroyed and memory is released.
❌ But if there’s a circular reference inside objects, GC kicks in.
🌀 2. Circular References in Classes
<?php
class A {
public $ref;
}
class B {
public $ref;
}
$a = new A();
$b = new B();
$a->ref = $b;
$b->ref = $a; // <- circular reference
unset($a, $b); // memory NOT immediately freed
gc_collect_cycles(); // manually free cycles
?>
➡️ Without GC, long-running scripts (like workers) would slowly eat up RAM.
📄 3. PDF Generation Example (Memory Heavy)
Suppose you’re using dompdf or TCPDF in Laravel/PHP.
<?php
use Dompdf\Dompdf;
function generatePDF($data) {
$dompdf = new Dompdf();
$dompdf->loadHtml("<h1>Hello $data</h1>");
$dompdf->render();
$pdf = $dompdf->output();
file_put_contents("output.pdf", $pdf);
// Free memory explicitly
unset($dompdf, $pdf);
gc_collect_cycles(); // cleanup
}
generatePDF("Ahmed");
?>
⚠️ Problem: If you generate thousands of PDFs in a queue job without cleanup, memory keeps rising.
✅ Solution: unset()
variables, call gc_collect_cycles()
occasionally.
📊 4. Excel Generation Example (Maatwebsite / PhpSpreadsheet)
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
function generateExcel() {
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello Ahmed');
$writer = new Xlsx($spreadsheet);
$writer->save('output.xlsx');
// Free memory
$spreadsheet->disconnectWorksheets();
unset($spreadsheet, $writer);
gc_collect_cycles();
}
generateExcel();
?>
⚠️ If you create 100,000+ rows without cleaning up, memory will spike (hundreds of MBs).
✅ Best practice:
- Use chunked writes (write in batches instead of loading everything in memory).
- Always
unset()
objects and callgc_collect_cycles()
in long-running scripts.
🚀 5. Real-World Tips (Laravel Jobs / Workers)
- For short web requests: memory is freed at the end of the request anyway.
-
For long-running jobs (queues, daemons, APIs that loop over big datasets):
- Always
unset()
large objects after use. - Call
gc_collect_cycles()
every few iterations. - For Excel, prefer
->store()
with queue exports (Maatwebsite handles memory better). - For PDF, generate and store in chunks instead of bulk in one go.
- Always
Let’s clear the confusion — why do we need to unset()
and call gc_collect_cycles()
in PDF (or Excel) generation, even though variables go out of scope?
🧠 1. Normal Case – Variables Go Out of Scope
In a short script or a web request, PHP automatically:
- Destroys variables when they go out of scope
- Frees memory when the request ends
Example:
function test() {
$a = "hello"; // allocated
} // <- function ends, $a destroyed, memory freed
➡️ Nothing special needed.
🧾 2. Why PDF/Excel is Different
Libraries like Dompdf, TCPDF, PhpSpreadsheet are heavy:
- They create big objects in memory (fonts, images, large buffers, XML tree for Excel, etc.)
- Some of these objects reference each other (circular references)
- PHP’s normal “out of scope” cleanup can’t immediately free all memory because circular references stay alive until GC runs
So, if you’re generating 1 PDF in a request, it doesn’t matter — memory is freed at request end.
But if you’re generating 100 PDFs in a loop (long-running worker), memory keeps growing until GC decides to run.
🔄 3. Example: PDF Without Explicit Cleanup
use Dompdf\Dompdf;
for ($i = 0; $i < 100; $i++) {
$dompdf = new Dompdf();
$dompdf->loadHtml("<h1>PDF $i</h1>");
$dompdf->render();
file_put_contents("pdf_$i.pdf", $dompdf->output());
// no unset or GC
}
⚠️ Problem: Memory grows with each loop because internal buffers & objects remain in circular references.
Eventually → script crashes with Out of Memory error.
✅ 4. With Explicit Cleanup
use Dompdf\Dompdf;
for ($i = 0; $i < 100; $i++) {
$dompdf = new Dompdf();
$dompdf->loadHtml("<h1>PDF $i</h1>");
$dompdf->render();
file_put_contents("pdf_$i.pdf", $dompdf->output());
// Cleanup
unset($dompdf);
gc_collect_cycles(); // force GC to break cycles
}
✔️ Memory stays stable, script runs fine.
⚡ 5. Key Difference
- Short script/web request → memory is freed when request ends (no worries).
- Long-running jobs (queue workers, daemons, batch processing) → memory accumulates unless you explicitly free heavy objects.
📝 Rule of Thumb
- For normal requests: don’t bother, PHP cleans up.
- For batch jobs / loops / workers: always
unset()
heavy objects and occasionally callgc_collect_cycles()
.
👉 That’s why for PDF/Excel generation in bulk, we explicitly free memory — not because PHP won’t free it at all, but because waiting until the script ends is too late for long-running processes.
✅ In summary:
- Classes & methods free memory normally.
- Garbage Collection is important when objects reference each other (circular refs).
- For PDF/Excel generation, explicitly free memory (
unset
,disconnectWorksheets
,gc_collect_cycles
) to prevent leaks. - In queues/long-running jobs, this is critical to avoid servers crashing from memory bloat.