detect-memory-issues
Memory Issue Detection
Analyze PHP code for memory usage problems.
Detection Patterns
1. Large Arrays in Memory
// MEMORY HOG: Loading entire table
$users = $repository->findAll(); // 1M users = OOM
foreach ($users as $user) {
process($user);
}
// MEMORY HOG: Building large array
$data = [];
foreach ($hugeDataset as $item) {
$data[] = transform($item); // Array grows unbounded
}
// FIXED: Use generator
function processUsers(Repository $repo): Generator {
foreach ($repo->iterate() as $user) {
yield transform($user);
}
}
2. Missing Generators
// MEMORY HOG: Entire file in memory
$lines = file('large-file.txt'); // 1GB file = OOM
foreach ($lines as $line) {
process($line);
}
// FIXED: Generator-based reading
function readLines(string $path): Generator {
$handle = fopen($path, 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
fclose($handle);
}
// MEMORY HOG: Collect then process
function getAllProducts(): array {
$products = [];
foreach ($this->fetchBatch() as $batch) {
$products = array_merge($products, $batch);
}
return $products; // Entire dataset
}
3. Unbounded Data Loading
// MEMORY HOG: No LIMIT
$logs = $repository->findBy(['level' => 'error']);
// Could be millions of records
// MEMORY HOG: Pagination loading all
$page = 1;
$allItems = [];
do {
$items = $api->fetch($page++);
$allItems = array_merge($allItems, $items);
} while (!empty($items));
// FIXED: Process in batches
$page = 1;
do {
$items = $api->fetch($page++);
foreach ($items as $item) {
yield $item;
}
} while (!empty($items));
4. Object Graph Loading
// MEMORY HOG: Deep object graph
$department = $repo->find($id);
$employees = $department->getEmployees(); // Loads all
foreach ($employees as $emp) {
$projects = $emp->getProjects(); // Loads more
foreach ($projects as $project) {
$tasks = $project->getTasks(); // Even more
}
}
// Entire object graph in memory
5. String Concatenation in Loop
// MEMORY HOG: String grows each iteration
$output = '';
foreach ($lines as $line) {
$output .= $line . "\n"; // Creates new string each time
}
// FIXED: Use array and implode
$parts = [];
foreach ($lines as $line) {
$parts[] = $line;
}
$output = implode("\n", $parts);
// BETTER: Use stream
$handle = fopen('output.txt', 'w');
foreach ($lines as $line) {
fwrite($handle, $line . "\n");
}
6. Image/Binary Processing
// MEMORY HOG: Entire image in memory
$image = file_get_contents('large-image.jpg');
$processed = processImage($image);
file_put_contents('output.jpg', $processed);
// MEMORY HOG: Multiple image resources
foreach ($images as $path) {
$img = imagecreatefromjpeg($path);
$resized = imagescale($img, 100, 100);
imagejpeg($resized, $outPath);
// Missing: imagedestroy($img); imagedestroy($resized);
}
7. Cache/Buffer Growth
// MEMORY LEAK: Cache grows unbounded
class Cache {
private array $data = [];
public function get(string $key): mixed {
if (!isset($this->data[$key])) {
$this->data[$key] = $this->load($key);
// Never evicted
}
return $this->data[$key];
}
}
// MEMORY LEAK: Event listeners accumulate
$dispatcher->addListener('event', function() {
// New closure each time
});
8. Doctrine Batch Processing
// MEMORY HOG: Doctrine identity map
foreach ($repository->findAll() as $entity) {
$entity->process();
$em->flush(); // Identity map keeps all entities
}
// FIXED: Clear periodically
$batchSize = 100;
$i = 0;
foreach ($repository->iterate() as $entity) {
$entity->process();
if (++$i % $batchSize === 0) {
$em->flush();
$em->clear(); // Free memory
}
}
$em->flush();
9. Session/Global Storage
// MEMORY HOG: Large session data
$_SESSION['search_results'] = $hugeArray;
// MEMORY HOG: Static cache
class Service {
private static array $cache = [];
public static function process($item) {
self::$cache[$item->getId()] = $item;
// Never cleared
}
}
Grep Patterns
# file() usage
Grep: "file\([^)]+\)" --glob "**/*.php"
# findAll without iterate
Grep: "->findAll\(\)" --glob "**/*.php"
# array_merge in loop
Grep: "foreach.*array_merge" --glob "**/*.php"
# String concatenation in loop
Grep: 'foreach.*\.=' --glob "**/*.php"
# Static array properties
Grep: "private static array" --glob "**/*.php"
Memory Estimation
| Operation | Memory Usage |
|---|---|
| 1M integers in array | ~32 MB |
| 1M strings (avg 50 chars) | ~250 MB |
| 1M Doctrine entities | ~500 MB - 2 GB |
| 1 GB file via file() | ~1 GB + overhead |
Severity Classification
| Pattern | Severity |
|---|---|
| Unbounded data loading | π΄ Critical |
| Full table in memory | π΄ Critical |
| Missing imagedestroy | π Major |
| Static cache without limit | π Major |
| String concat in loop | π‘ Minor |
Output Format
### Memory Issue: [Description]
**Severity:** π΄/π /π‘
**Location:** `file.php:line`
**Estimated Memory:** ~500 MB for 100K records
**Issue:**
[Description of the memory problem]
**Code:**
```php
// Memory-intensive code
Fix:
// Memory-efficient alternative
Memory Reduction: Before: ~500 MB peak After: ~10 MB peak (streaming)
## When This Is Acceptable
- **CLI commands/workers** β Console commands may legitimately use more memory for batch processing
- **Known bounded datasets** β Loading all items when the table is guaranteed small (e.g., countries, currencies)
- **Cached data** β Large arrays that are built once and cached for reuse
### False Positive Indicators
- Code is in a console command or queue worker with explicit memory management
- Collection is loaded from a known-small dataset (< 1000 records by business rule)
- Large array is built for cache warming with explicit garbage collection
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12