首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用“实际使用”的memory_get_peak_usage()

使用“实际使用”的memory_get_peak_usage()
EN

Stack Overflow用户
提问于 2013-04-01 22:32:44
回答 5查看 75.3K关注 0票数 97

如果将real_usage参数设置为true,PHP DOCS表示它将获得从系统分配的实际内存大小。如果它是false,它将获得emalloc()报告的内存

这两个选项中哪一个返回最大值。相对于php.ini中的内存限制值分配的内存?

我想知道脚本离达到这个极限有多近。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-04-26 22:53:08

好的,让我们用一个简单的脚本来测试一下:

代码语言:javascript
运行
复制
ini_set('memory_limit', '1M');
$x = '';
while(true) {
  echo "not real: ".(memory_get_peak_usage(false)/1024/1024)." MiB\n";
  echo "real: ".(memory_get_peak_usage(true)/1024/1024)." MiB\n\n";
  $x .= str_repeat(' ', 1024*25); //store 25kb more to string
}

输出:

代码语言:javascript
运行
复制
not real: 0.73469543457031 MiB
real: 0.75 MiB

not real: 0.75910949707031 MiB
real: 1 MiB

...

not real: 0.95442199707031 MiB
real: 1 MiB

not real: 0.97883605957031 MiB
real: 1 MiB

PHP Fatal error:  Allowed memory size of 1048576 bytes exhausted (tried to allocate 793601 bytes) in /home/niko/test.php on line 7

看起来真正的使用率是从系统分配的内存--似乎是在比脚本当前需要的更大的存储桶中分配的。(我猜是出于性能原因)。这也是php进程使用的内存。

$real_usage = false使用率是您在脚本中实际使用的内存使用量,而不是Zend内存管理器分配的实际内存量。

有关更多信息,请阅读this question

简而言之:要获得内存限制的近似值,可以使用$real_usage = true

票数 147
EN

Stack Overflow用户

发布于 2013-04-27 04:51:46

简介

您应该使用memory_get_usage(false),因为您需要的是使用的内存,而不是分配的内存。

有什么不同

您的Google Mail可能已经为您分配了25MB的存储空间,但这并不意味着您现在就在使用它。

这正是PHP文档所说的

将其设置为TRUE,以获取从系统分配的实际内存大小。如果未设置或设置为FALSE,则只报告emalloc()使用的内存。

这两个参数都会返回相对于内存限制分配的内存,但主要区别是:

memory_get_usage(false)给出了emalloc()使用的内存,而memory_get_usage(true)返回了里程碑,可以在这里演示Memory Mile Store

我想知道脚本距离达到这个限制有多近。

这需要一些数学计算,并且可能只在循环或特定用例中有效。为何我会这样说呢?

想象一下

代码语言:javascript
运行
复制
ini_set('memory_limit', '1M');
$data = str_repeat(' ', 1024 * 1024);

The above script would fail before you even get the chance to start start checking memory

据我所知,检查用于PHP变量或特定部分的内存的唯一方法是:

代码语言:javascript
运行
复制
$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;

See Explanation,但如果您在循环或递归函数中,您可以使用最大内存使用量来安全地估计何时会达到内存峰值。

示例

代码语言:javascript
运行
复制
ini_set('memory_limit', '1M');

$memoryAvailable = filter_var(ini_get("memory_limit"), FILTER_SANITIZE_NUMBER_INT);
$memoryAvailable = $memoryAvailable * 1024 * 1024;

$peekPoint = 90; // 90%

$memoryStart = memory_get_peak_usage(false);
$memoryDiff = 0;

// Some stats
$stat = array(
        "HIGHEST_MEMORY" => 0,
        "HIGHEST_DIFF" => 0,
        "PERCENTAGE_BREAK" => 0,
        "AVERAGE" => array(),
        "LOOPS" => 0
);

$data = "";
$i = 0;
while ( true ) {
    $i ++;

    // Get used memory
    $memoryUsed = memory_get_peak_usage(false);

    // Get Diffrence
    $memoryDiff = $memoryUsed - $memoryStart;

    // Start memory Usage again
    $memoryStart = memory_get_peak_usage(false);

    // Gather some stats
    $stat['HIGHEST_MEMORY'] = $memoryUsed > $stat['HIGHEST_MEMORY'] ? $memoryUsed : $stat['HIGHEST_MEMORY'];
    $stat['HIGHEST_DIFF'] = $memoryDiff > $stat['HIGHEST_DIFF'] ? $memoryDiff : $stat['HIGHEST_DIFF'];
    $stat['AVERAGE'][] = $memoryDiff;
    $stat['LOOPS'] ++;
    $percentage = (($memoryUsed + $stat['HIGHEST_DIFF']) / $memoryAvailable) * 100;

    // var_dump($percentage, $memoryDiff);

    // Stop your scipt
    if ($percentage > $peekPoint) {

        print(sprintf("Stoped at: %0.2f", $percentage) . "%\n");
        $stat['AVERAGE'] = array_sum($stat['AVERAGE']) / count($stat['AVERAGE']);
        $stat = array_map(function ($v) {
            return sprintf("%0.2f", $v / (1024 * 1024));
        }, $stat);
        $stat['LOOPS'] = $i;
        $stat['PERCENTAGE_BREAK'] = sprintf("%0.2f", $percentage) . "%";
        echo json_encode($stat, 128);
        break;
    }

    $data .= str_repeat(' ', 1024 * 25); // 1kb every time
}

Output

代码语言:javascript
运行
复制
Stoped at: 95.86%
{
    "HIGHEST_MEMORY": "0.71",
    "HIGHEST_DIFF": "0.24",
    "PERCENTAGE_BREAK": "95.86%",
    "AVERAGE": "0.04",
    "LOOPS": 11
}

Live Demo

此操作可能仍会失败

它可能会失败,因为在if ($percentage > $peekPoint) {之后,这仍然需要添加额外任务,同时也会消耗内存

代码语言:javascript
运行
复制
        print(sprintf("Stoped at: %0.2f", $percentage) . "%\n");
        $stat['AVERAGE'] = array_sum($stat['AVERAGE']) / count($stat['AVERAGE']);
        $stat = array_map(function ($v) {
            return sprintf("%0.2f", $v / (1024 * 1024));
        }, $stat);
        $stat['LOOPS'] = $i;
        $stat['PERCENTAGE_BREAK'] = sprintf("%0.2f", $percentage) . "%";
        echo json_encode($stat, 128);
        break;

If the memory to process this request is grater than the memory available the script would fail.

结论

这不是一个完美的解决方案,但请每隔一段时间检查内存,如果内存超过peek (如90%) exit,则立即离开那些花哨的东西

票数 38
EN

Stack Overflow用户

发布于 2013-04-26 21:57:06

real_usage false报告您的脚本使用的情况。这将是两者中更准确的一个。

real_usage true报告分配给脚本的内存。这将是两者中较高的一个。

如果我试图进行比较,我可能会使用true,因为您的脚本分配的内存永远不会超过内存限制,并且只要它(以及所有其他脚本)不超过内存限制,它就会继续运行。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15745385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档