允许的#字节内存大小已耗尽

我遇到了可怕的错误消息,可能是经过艰苦的努力,PHP已经耗尽内存:

在第123行的file.php中允许####字节的内存大小已耗尽(试图分配####字节)

增加限制

如果你知道你在做什么,并想增加限制,请参阅memory_limit:

ini_set('memory_limit', '16M');
ini_set('memory_limit', -1); // no limit

谨防! 你可能只是在解决症状而不是问题!

诊断泄漏:

该错误消息指向一条循环,我认为这个循环会泄漏或不必要地累积内存。 我在每次迭代结束时都会打印memory_get_usage()语句,并可以看到数字缓慢增长,直到达到极限:

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
}

出于这个问题的目的,我们假设可以想象的最糟糕的意大利面代码隐藏在全局范围的$userTask

什么工具,PHP技巧或调试巫术可以帮助我找到并解决问题?


PHP没有垃圾收集器。 它使用引用计数来管理内存。 因此,最常见的内存泄漏来源是循环引用和全局变量。 如果你使用一个框架,恐怕会有很多代码来寻找它。 最简单的工具是有选择地调用memory_get_usage并将其缩小到代码泄漏的位置。 您也可以使用xdebug创建代码的跟踪。 使用执行跟踪和show_mem_delta运行代码。


在php中有几种可能的内存泄漏点:

  • PHP本身
  • PHP扩展
  • 你使用的php库
  • 你的php代码
  • 如果没有深度逆向工程或php源代码知识,很难找到并修复前3个。 对于最后一个,你可以使用memory_get_usage对二进制搜索内存泄漏代码


    这是我们用来确定哪些脚本在我们的服务器上使用最多内存的技巧。

    将以下片段保存在文件中,例如/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 $urln", 3, '/var/log/httpd/php_memory_log');
    }
    register_shutdown_function('strangecode_log_memory_usage');
    

    通过将以下内容添加到httpd.conf中来应用它:

    php_admin_value auto_prepend_file /usr/local/lib/php/strangecode_log_memory_usage.inc.php
    

    然后分析/var/log/httpd/php_memory_log的日志文件

    在Web用户可以写入日志文件之前,您可能需要先touch /var/log/httpd/php_memory_log && chmod 666 /var/log/httpd/php_memory_log

    链接地址: http://www.djcxy.com/p/19919.html

    上一篇: Allowed memory size of # bytes exhausted

    下一篇: Is there an acceptable limit for memory leaks?