简体   繁体   中英

How to “drilldown” memory_get_usage() in PHP to find memory leaks?

I have a script that sometimes break because I get an error like:

PHP Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes) in ...

The memory limit is NOT too low and was put at 128M. (This should be more than enough.)

The problem is that as the script goes, it takes more and more memory. Basically, it's a for loop. I've checked every variable but there is no place where the script fills 'something' (for example, an array) that would grow and explain why the script takes more memory.

I confirmed the memory problem using: memory_get_usage() . I've printed out the memory footprint after each iteration and the number is always higher.

Using Xdebug does show not any sign that can help me at this point.

Is there any way I could drilldown and know what is taking more memory everytime I loop ? What would you suggest to debug that situation ?

The short answer is: it's not possible to drilldown.

That said, the way I found what the problem was is that I splitted the code inside the loop in subfunctions. Then, I commented them all to only check what was the footprint of looping without doing anything. Then, I've uncommented function by function until I found the problematic one.

Once I've got the problematic function, I did the same process again: comment everything in it then uncomment until I find the problematic piece of code.

I finally found that I was calling a function that used create_function from PHP. Many people are 'complaining' about 'memory leaks' from this function. The problem is not a memory leak but instead the fact that if you call the create_function in a loop, it will really create as many functions as the number of times you loop. To avoid this, I've found this concept to avoid recreating the function thousands of times.

<?php 
global $my_func; 
if (!isset($my_func)) { 
    $my_func = create_function($args, $code); 
}

$my_func(); 
?>

Adapting the code to make sure the function is created only once solved the problem. The whole script now takes only 8MB of memory instead of breaking after busting over 128MB.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM