跟踪 PHP 中的内存使用情况

2022-08-30 13:39:51

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

我已经使用了一些积极的结果。添加标志会有所帮助(不太清楚“系统”内存和“emalloc”内存之间的区别,但系统显示的数字更大)。 随着 URL 的添加而增加,然后在 URL 集耗尽时下降。但是,我刚刚超过了32M的限制,我上次的内存检查是~18M。memory_get_usage()real_usagememory_get_usage()

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

[更新:在询问我猜之前应该运行更多的测试,增加了php的内存限制(但在脚本中保留了“安全”量不变),并且报告的内存使用量确实从我自己施加的25M限制以下跃升到超过32M。然后,正如预期的那样,作为未添加的URL缓慢下降。但我要把问题留到:这是正确的方法吗?

我能以这种方式信任吗?有没有更好的替代方法来获取内存使用情况(我见过一些脚本解析shell命令的输出)?memory_get_usage()


答案 1

real_usage工作方式如下:

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

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

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

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

另请参阅有关此内存管理器的文章,它也有一些代码示例。


答案 2

我也假设是安全的,但我想你可以比较这两种方法并自己决定,这里有一个解析系统调用的函数: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, '.', '');
}

推荐