How do you debug php “Out of Memory” issues?

前端 未结 6 806
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-09 02:46

I\'ve had some issues lately with PHP memory limits lately:

Out of memory (allocated 22544384) (tried to allocate 232 bytes)

<
相关标签:
6条回答
  • 2020-12-09 03:04

    Check the documentation of the function memory_get_usage() to view the memory usage in run time.

    0 讨论(0)
  • 2020-12-09 03:04

    Use xdebug to profile memory usage.

    0 讨论(0)
  • 2020-12-09 03:05

    Memprof is a php extension that helps finding those memory-eaters snippets, specially in object-oriented codes.

    This adapted tutorial is quite useful.

    Note: I unsuccessfully tried to compile this extension for windows. If you try so, be sure your php is not thread safe. To avoid some headaches I suggest you to use it under *nix environments.

    Another interesting link was a slideshare describing how php handles memory. It gives you some clues about your script's memory usage.

    0 讨论(0)
  • 2020-12-09 03:15

    I wonder is perhaps your thinking regards methodology is flawed here.

    The basic answer to your question - how do I find out where this error is occurring? - has already been answered; you know what's causing that.

    However, this is one of those cases where the triggering error isn't really the problem - certainly, that 232 byte object isn't your problem at all. It is the 20+Megs that was allocated before it.

    There have been some ideas posted which can help you track that down; you really need to look "higher level" here, at the application architecture, and not just at individual functions.

    It may be that your application requires more memory to do what it does, with the user load you have. Or it may be that there are some real memory hogs that are unnecessary - but you have to know what is necessary or not to answer that question.

    That basically means going line-by-line, object-by-object, profiling as needed, until you find what you seek; big memory users. Note that there might not be one or two big items... if only it were so easy! Once you find the memory-hogs, you then have to figure out if they can be optimized. If not, then you need more memory.

    0 讨论(0)
  • 2020-12-09 03:16

    Website "IF !1 0" provides a simple to use MemoryUsageInformation class. It is very useful for debugging memory leaks.

    <?php
    
    class MemoryUsageInformation
    {
    
        private $real_usage;
        private $statistics = array();
    
        // Memory Usage Information constructor
        public function __construct($real_usage = false)
        {
            $this->real_usage = $real_usage;
        }
    
        // Returns current memory usage with or without styling
        public function getCurrentMemoryUsage($with_style = true)
        {
            $mem = memory_get_usage($this->real_usage);
            return ($with_style) ? $this->byteFormat($mem) : $mem;
        }
    
        // Returns peak of memory usage
        public function getPeakMemoryUsage($with_style = true)
        {
            $mem = memory_get_peak_usage($this->real_usage);
            return ($with_style) ? $this->byteFormat($mem) : $mem;
        }
    
        // Set memory usage with info
        public function setMemoryUsage($info = '')
        {
            $this->statistics[] = array('time' => time(),
                'info' => $info,
                'memory_usage' => $this->getCurrentMemoryUsage());
        }
    
        // Print all memory usage info and memory limit and 
        public function printMemoryUsageInformation()
        {
            foreach ($this->statistics as $satistic)
            {
                echo "Time: " . $satistic['time'] .
                " | Memory Usage: " . $satistic['memory_usage'] .
                " | Info: " . $satistic['info'];
                echo "\n";
            }
            echo "\n\n";
            echo "Peak of memory usage: " . $this->getPeakMemoryUsage();
            echo "\n\n";
        }
    
        // Set start with default info or some custom info
        public function setStart($info = 'Initial Memory Usage')
        {
            $this->setMemoryUsage($info);
        }
    
        // Set end with default info or some custom info
        public function setEnd($info = 'Memory Usage at the End')
        {
            $this->setMemoryUsage($info);
        }
    
        // Byte formatting
        private function byteFormat($bytes, $unit = "", $decimals = 2)
        {
            $units = array('B' => 0, 'KB' => 1, 'MB' => 2, 'GB' => 3, 'TB' => 4,
                'PB' => 5, 'EB' => 6, 'ZB' => 7, 'YB' => 8);
    
            $value = 0;
            if ($bytes > 0)
            {
                // Generate automatic prefix by bytes 
                // If wrong prefix given
                if (!array_key_exists($unit, $units))
                {
                    $pow = floor(log($bytes) / log(1024));
                    $unit = array_search($pow, $units);
                }
    
                // Calculate byte value by prefix
                $value = ($bytes / pow(1024, floor($units[$unit])));
            }
    
            // If decimals is not numeric or decimals is less than 0 
            // then set default value
            if (!is_numeric($decimals) || $decimals < 0)
            {
                $decimals = 2;
            }
    
            // Format output
            return sprintf('%.' . $decimals . 'f ' . $unit, $value);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 03:17
    echo '<pre>';
    $vars = get_defined_vars();
    foreach($vars as $name=>$var)
    {
        echo '<strong>' . $name . '</strong>: ' . strlen(serialize($var)) . '<br />';
    }
    exit();
    
    /* ... Code that triggers memory error ... */
    

    I use this to print out a list of currently assigned variables just before a problem section of my code, along with a (very) rough estimate of the size of the variable. I go back and unset anything that isn't needed at and beyond the point of interest.

    It's useful when installing an extension isn't an option.

    You could modify the above code to use memory_get_usage in a way that will give you a different estimate of the memory in a variable, not sure whether it'd be better or worse.

    0 讨论(0)
提交回复
热议问题