题 跟踪PHP中的内存使用情况


我正在尝试跟踪处理URL的脚本的内存使用情况。基本思想是在将另一个URL添加到cURL多处理程序之前检查是否存在合理的缓冲区。我正在使用'滚动cURL'概念,在多处理程序运行时处理URL数据。这意味着每次现有URL处理并删除时,我都可以通过从池中添加新URL来保持N个连接处于活动状态。

我用过 memory_get_usage() 有一些积极的结果。添加 real_usage flag帮助(不清楚'系统'内存和'emalloc'内存之间的区别,但系统显示更大的数字)。 memory_get_usage() 随着URL设置的耗尽,URL会随着URL的增加而增加。但是,我刚刚超过32M限制,我的最后一次内存检查是~18M。

每次cURL多信号请求返回时,我都会轮询内存使用情况。由于多个请求可能同时返回,因此一堆URL可能同时返回数据并实际跳过14M的内存使用量。但是,如果 memory_get_usage() 是准确的,我想这就是发生了什么。

[更新:在我猜测之前应该运行更多测试,增加php的内存限制(但在脚本中保持'安全'数量相同)并且报告的内存使用率从我自己施加的限制25M下降到超过32M。然后,正如预期的那样缓慢下降为未添加的URL。但我会提出这个问题:这是正确的方法吗?]

我能相信吗? memory_get_usage() 通过这种方式?是否有更好的替代方法来获取内存(我已经看到一些脚本解析shell命令的输出)?


29
2018-02-18 17:11


起源




答案:


real_usage 这样工作:

Zend的内存管理器不会为它需要的每个块使用系统malloc。相反,它分配了一大块系统内存(以256K为增量,可以通过设置环境变量来更改) ZEND_MM_SEG_SIZE并在内部管理它。因此,有两种内存使用方式:

  1. 引擎从操作系统中获取了多少内存(“实际使用情况”)
  2. 应用程序实际使用了多少内存(“内部使用”)

其中任何一个都可以返回 memory_get_usage()。哪一个对您更有用取决于您正在研究的内容。如果您正在考虑在特定部分优化代码,“内部”可能对您更有用。如果您在全球范围内跟踪内存使用情况,那么“真实”会更有用。 memory_limit 限制“实际”数字,因此只要限制允许的所有块都从系统中获取并且内存管理器无法分配请求的块,分配就会失败。请注意,在这种情况下,“内部”使用可能小于限制,但由于碎片,分配仍可能失败。

此外,如果您使用的是某些外部存储器跟踪工具,则可以进行此设置 环境变量 USE_ZEND_ALLOC=0 这将禁用上述机制并使引擎始终使用 malloc()。这会有更糟糕的性能,但允许您使用malloc跟踪工具。

也可以看看 关于这个内存管理器的文章,它也有一些代码示例。


43
2018-02-18 18:07



404试图按照文章链接。唉。 - Michael Cordingley
@MichaelCordingley,试试这个: web.archive.org/web/20130719064612/http://www.ibm.com/... - StasM


我也假设 memory_get_usage() 是安全的,但我想你可以比较两种方法并自己决定,这是一个解析系统调用的函数:

function Memory_Usage($decimals = 2)
{
    $result = 0;

    if (function_exists('memory_get_usage'))
    {
        $result = memory_get_usage() / 1024;
    }

    else
    {
        if (function_exists('exec'))
        {
            $output = array();

            if (substr(strtoupper(PHP_OS), 0, 3) == 'WIN')
            {
                exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output);

                $result = preg_replace('/[\D]/', '', $output[5]);
            }

            else
            {
                exec('ps -eo%mem,rss,pid | grep ' . getmypid(), $output);

                $output = explode('  ', $output[0]);

                $result = $output[1];
            }
        }
    }

    return number_format(intval($result) / 1024, $decimals, '.', '');
}

7
2018-02-18 17:42



你最好使用“--pid”而不是grep,因为有一天你可能会得到一个等于你正在寻找的PID的RSS值并最终得到2行 - greg
你的代码返回的内存单位是什么? - Eshant Sahu
它是兆字节.. - M_R_K


使用 Xdebug的,因为它最近(29日1月)更新到现在包括内存分析信息。它跟踪函数调用和消耗的内存量。这使您可以非常深入地了解您的代码,并至少让您了解问题。

文档很有帮助,但基本上你,安装它可以启用分析 xdebug.profiler_enable = 1 并给出输出 xdebug.profiler_output_dir=/some/path 一个工具,如 qcachegrind 做重物,让视觉上看到它。


0
2018-02-19 19:32





好吧,我的PHP脚本从来没有真正出现过内存问题,所以我认为我找不到问题的原因有多大帮助,但我可以推荐的是你得到一个PHP加速器,你会注意到性能的提高和内存使用率下降。这是一个加速器列表和一篇比较其中几个的文章(性能提高3倍)

维基百科名单

基准

基准测试已有2年的历史,但您可以了解性能的提升。

如果你不得不这样做,你也可以增加你在PHP中的内存限制,如果你仍然有加速器的问题。打开你的php.ini并找到:

memory_limit = 32M;

并且稍微增加一点。


-5
2018-02-18 17:18



是的,这就是这个项目未来的所有东西,现在只是尽可能地保持脚本排队。问题是我希望它使用它给出的内存。 - Tim Lytle