memory_get_peak_usage(),带有“真实用途”

问题描述 投票:81回答:5

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

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

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

php memory memory-management
5个回答
120
投票

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

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
}

输出:

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


32
投票

介绍

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

有什么不同

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

这正是PHP文档所说的

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

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

memory_get_usage(false)emalloc()使用的记忆,而memory_get_usage(true)返回里程碑,这可以在这里示范Memory Mile Store

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

这需要一些数学,可能只适用于循环或特定用例。我为什么这么说?

想像

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的变量或特定部分的内存的唯一方法是:

$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;

See Explanation,但是如果你处于循环或递归函数中,你可以使用最大内存使用量来安全地估计何时可以达到内存查看。

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

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) {之后,这仍然会增加执行额外的任务,同时也消耗内存

        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.

结论

它不是一个完美的解决方案,但检查间隔内存,如果它超过偷看(例如90%)exit立即,并留下花哨的东西


7
投票

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

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

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


2
投票

根据PHP memory_get_usage

real_usage

将其设置为TRUE以从系统分配总内存,包括未使用的页面。如果未设置或FALSE,则仅报告已使用的内存。

因此,要获取脚本使用的内存,应使用memory_get_usage()作为默认值,real_usage为false。

如果你想获得系统分配的内存但不关心实际使用了多少,请使用memory_get_usage(true);


0
投票
<!-- Print CPU memory and load -->
<?php
$output = shell_exec('free');
$data = substr($output,111,19);
echo $data;
echo file_get_contents('/proc/loadavg');
$load = sys_getloadavg();
$res = implode("",$load);
echo $res;
?>
© www.soinside.com 2019 - 2024. All rights reserved.