web-dev-qa-db-ja.com

「実際の使用量」を指定したmemory_get_peak_usage()

real_usage引数がtrueに設定されている場合、PHP DOCSはシステムから割り当てられたメモリの実際のサイズを取得すると言います。 falseの場合、emalloc()によって報告されたメモリを取得します

これらの2つのオプションのいずれが最大値を返します。 php.iniのメモリ制限値に対して割り当てられたメモリ?

スクリプトがその制限にどれだけ近づいたかを知りたい。

83
thelolcat

わかりました、簡単なスクリプトを使用してこれをテストしましょう:

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のメモリマネージャによって割り当てられた実際のメモリ量ではありません。

詳細については、 この質問 を参照してください。

つまり、メモリ制限にどれだけ近いかを確認するには、$real_usage = trueを使用します

121
Niko Sams

はじめに

memory_get_usage(false)を使用する必要があります。これは、割り当てられたメモリではなく、使用されるメモリが必要なためです。

Whats the Difference

Google Mail25MBのストレージを割り当てている可能性がありますが、それが現時点で使用しているわけではありません。

これはまさに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;

説明を参照 。ただし、ループまたは再帰関数を使用している場合は、最大メモリ使用量を使用して、メモリピークに達するタイミングを安全に推定できます。

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
}

出力

Stoped at: 95.86%
{
    "HIGHEST_MEMORY": "0.71",
    "HIGHEST_DIFF": "0.24",
    "PERCENTAGE_BREAK": "95.86%",
    "AVERAGE": "0.04",
    "LOOPS": 11
}

ライブデモ

これでも失敗する可能性があります

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を即座に超えて派手なものを残す場合

33
Baba

real_usage falseは、スクリプトの使用状況を報告しますsed。これは、2つのうちより正確です。

real_usage trueはメモリを報告します割り当て済みスクリプトに。これは2つのうち高い方になります。

あなたのスクリプトはメモリ制限を超えて割り当てられることはなく、その使用量(および他のすべてのスクリプト)がその使用量を超えない限り実行を続けるため、比較しようとする場合はおそらくtrueを使用します。 。

7
Glitch Desire

PHP memory_get_usage に従って

real_usage

これをTRUEに設定すると、未使用ページを含むシステムから割り当てられた合計メモリが取得されます。設定されていないか、FALSEの場合、使用されたメモリのみが報告されます。

スクリプトで使用されるメモリを取得するには、デフォルトのreal_usageがfalseであるため、memory_get_usage()を使用する必要があります。

システムによって割り当てられたメモリを取得したいが、実際に使用された量を気にしない場合は、memory_get_usage(true)を使用します。

2
Tofeeq
<!-- 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;
?>
0
Rahul Rohewal