I've encountered the dreaded error-message, possibly through-painstaking effort, PHP has run out of memory:
Allowed memory size of #### bytes exhausted (tried to allocate #### bytes) in file.php on line 123
If you know what you're doing and want to increase the limit see memory_limit:
ini_set('memory_limit', '16M'); ini_set('memory_limit', -1); // no limit
Beware! You may only be solving the symptom and not the problem!
The error message points to a line withing a loop that I believe to be leaking, or needlessly-accumulating, memory. I've printed memory_get_usage()
statements at the end of each iteration and can see the number slowly grow until it reaches the limit:
foreach ($users as $user) { $task = new Task; $task->run($user); unset($task); // Free the variable in an attempt to recover memory print memory_get_usage(true); // increases over time }
For the purposes of this question let's assume the worst spaghetti code imaginable is hiding in global-scope somewhere in $user
or Task
.
What tools, PHP tricks, or debugging voodoo can help me find and fix the problem?
One way to check for memory leak is to press and hold down your Windows key and tap the Pause/Break key to bring up System Properties. Click on the Performance tab and check System Resources for the percentage of free or available RAM.
The correct way is to edit your php. ini file. Edit memory_limit to your desire value. As from your question, 128M (which is the default limit) has been exceeded, so there is something seriously wrong with your code as it should not take that much.
Memory leaks are when programs on the computer incorrectly manage memory allocations. This is not uncommon on modern software and can cause performance drags on the system. The easiest way to fix this issue is to close and reopen the program with the leak, as it will reset the allocations.
Try prefixing your command with COMPOSER_MEMORY_LIMIT=-1 . This will remove the memory limit for the execution of the command. Update: Memory exhaust errors should now be resolved by using Composer 2.
PHP doesn't have a garbage collector. It uses reference counting to manage memory. Thus, the most common source of memory leaks are cyclic references and global variables. If you use a framework, you'll have a lot of code to trawl through to find it, I'm afraid. The simplest instrument is to selectively place calls to memory_get_usage
and narrow it down to where the code leaks. You can also use xdebug to create a trace of the code. Run the code with execution traces and show_mem_delta
.
Here's a trick we've used to identify which scripts are using the most memory on our server.
Save the following snippet in a file at, e.g., /usr/local/lib/php/strangecode_log_memory_usage.inc.php
:
<?php function strangecode_log_memory_usage() { $site = '' == getenv('SERVER_NAME') ? getenv('SCRIPT_FILENAME') : getenv('SERVER_NAME'); $url = $_SERVER['PHP_SELF']; $current = memory_get_usage(); $peak = memory_get_peak_usage(); error_log("$site current: $current peak: $peak $url\n", 3, '/var/log/httpd/php_memory_log'); } register_shutdown_function('strangecode_log_memory_usage');
Employ it by adding the following to httpd.conf:
php_admin_value auto_prepend_file /usr/local/lib/php/strangecode_log_memory_usage.inc.php
Then analyze the log file at /var/log/httpd/php_memory_log
You might need to touch /var/log/httpd/php_memory_log && chmod 666 /var/log/httpd/php_memory_log
before your web user can write to the log file.
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