"실제 사용량"이있는 memory_get_peak_usage ()


94

real_usage인수가 truePHP DOCS 로 설정 되면 시스템에서 할당 된 실제 메모리 크기를 가져옵니다. 그것이 있다면 그것은 false보고 된 메모리를 얻을 것입니다emalloc()

이 두 가지 옵션 중 어느 것이 최대 값을 반환합니까? php.ini의 메모리 제한 값에 상대적으로 할당 된 메모리?

스크립트가 그 한계에 얼마나 근접했는지 알고 싶습니다.


8
Julien Pauli youtube.com/watch?v=sm1HUrnsxLI 의 PHP uk 컨퍼런스 2013에서 PHP 내부에서 메모리가 작동하는 방식에 대해 설명 하는 프레젠테이션을 소개합니다 .
mpratt 2013

답변:


138

좋습니다. 간단한 스크립트를 사용하여 테스트 해 보겠습니다.

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사용은 당신이 실제로 스크립트에 사용되는 메모리 사용하지 젠드의 메모리 관리자에 의해 할당 된 메모리의 실제 양이다.

자세한 내용은 이 질문 을 읽으십시오 .

요컨대 : 메모리 한계에 얼마나 근접했는지 확인하려면 $real_usage = true


5
Zend 엔진은 256K 청크로 메모리를 할당합니다. "실제 사용량"값은 이러한 모든 청크의 합계입니다. 실제로 메모리 소모 오류를 트리거하는 데 사용되는 값 if (segment_size < true_size || heap->real_size + segment_size > heap->limit) { /* Memory limit overflow */입니다.
cleong

2
"실수가 아님"값은 호출에서 요청한 emalloc바이트 수 (헤더 및 메모리 정렬을위한 바이트 더하기 )의 합계입니다 . 이미 할당 된 세그먼트에 남아있는 공간에 맞지 않는 블록으로 인해 낭비되는 메모리는 반영되지 않습니다. (1024 * 256) 바이트와 2M 제한을 할당하도록 예제를 변경하면 두 가지 차이가 ​​더 분명해집니다.
cleong

@Niko, 왜 memory_get_usage 대신 memory_get_peak_usage를 사용 했습니까? 더 정확한 결과를 얻기 위해 gc_disable ()을 사용하고 memory_get_usage를 사용해야하지 않습니까?
Pacerier

그 피크 차종 내가 말하고 싶지만 감각 - 문제는 스크립트가 얼마나 가까운 한계 얻을 수 있었다 @Pacerier
니코 Sams에

4
@cleong이 설명했듯이 모든 찬성에도 불구 하고이 대답은 실제로 잘못되었습니다. memory_get_usage(true)와 비교되어야 하는 반환 값입니다 memory_limit. 대답에 주어진 예는 "낭비 된"메모리가 없기 때문에 너무 간단합니다. "실제"할당 된 메모리를 "1MiB"에서 "1.25MiB"로 늘려야하고 이것이 치명적인 오류를 유발하는 것입니다. . "실제"할당 메모리가 제한에 도달하여 중단 될 때 "실제"할당 메모리가 "
80MiB"뿐인

37

소개

memory_get_usage(false)원하는 것은 할당 된 메모리가 아닌 사용 된 메모리이기 때문에 사용해야합니다 .

차이점이 뭐야

귀하 Google Mail가 귀하를 25MB위해 스토리지를 할당했을 수도 있지만 이것이 현재 사용한 스토리지임을 의미하지는 않습니다.

이것이 바로 PHP 문서가 말한 내용입니다.

시스템에서 할당 된 실제 메모리 크기를 얻으려면 TRUE로 설정하십시오. 설정하지 않거나 FALSE 인 경우 emalloc ()에서 사용하는 메모리 만보고됩니다.

두 인수 모두 메모리 제한에 상대적으로 할당 된 메모리를 반환하지만 주요 차이점은 다음과 같습니다.

memory_get_usage(false)여기에서 데모가 될 수있는 이정표를 반환 하는 emalloc()동안 사용 된 메모리를 제공합니다. Memory Mile Storememory_get_usage(true)

스크립트가 그 한계에 얼마나 근접했는지 알고 싶습니다.

그것은 약간의 수학이 필요하며 루프 또는 특정 사용 사례에서만 작동 할 수 있습니다. 내가 왜 그렇게 말했습니까?

상상

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.

결론

완벽한 솔루션은 아니지만 간격을두고 메모리를 확인하고 exit즉시 엿보기 (예 : 90 %)를 초과하는지 확인 하고 멋진 물건을 남겨 둡니다.


memory_limit힙에 대한 옵션? 아니면 스택?
Yousha Aleayoub

두 개의 스크립트가 병렬로 있거나 많은 요청이있는 경우, di memory_get_usage () 함수는 동시에 실행되는 모든 스크립트에 사용 된 메모리를 반환하거나 실제 스크립트 만 반환합니까?
Mohammed Yassine CHABLI

7

real_usagefalse는 스크립트가 사용한 사용량을보고합니다 . 이것은 둘 중 더 정확할 것입니다.

real_usagetrue는 스크립트에 할당 된 메모리를보고합니다 . 이것은 둘 중 더 높을 것입니다.

아마 사용하십시오 true스크립트가 더 많은 메모리 제한보다 할당되지 않을 것 같이 내가 비교하려고 한 경우, 그리고 그것이 (및 다른 모든 스크립트) 그 사용량을 초과하지 않은 것처럼 계속 실행됩니다.


1
그것은 정반대입니다 : false스크립트가 메모리입니다 사용 , true메모리입니다 할당은 .
Benjamin

1
@Benjamin 그래, 왜 그렇게 맹목적으로 틀렸는 지 모르겠습니다. 음, 수정되었습니다.
Glitch Desire

2

PHP memory_get_usage에 따라

real_usage

사용하지 않는 페이지를 포함하여 시스템에서 할당 된 총 메모리를 얻으려면 이것을 TRUE로 설정하십시오. 설정되지 않거나 FALSE 인 경우 사용 된 메모리 만보고됩니다.

따라서 스크립트에서 사용하는 메모리를 얻으려면 기본 real_usage가 false이므로 memory_get_usage ()를 사용해야합니다.

시스템에 의해 할당 된 메모리를 얻고 싶지만 실제로 얼마나 많이 사용되었는지 신경 쓰지 않는다면 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;
?>

2
Stackoverflow에 오신 것을 환영합니다! 답이 뭔지 말씀해 주 시겠어요? 코드뿐만 아니라 질문을 해결하는 방법을 알아 낸 방법도 있습니다. 감사!
Gilles Heinesch 19.04.15

귀하의 답변은 잠재적으로 유용한 정보를 제공 할 수 있지만 질문하는 질문과 관련이 없습니다. 귀하의 답변이 요청 된 질문과 어떤 관련이 있는지 설명 할 수 있습니다.
Moritur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.