memory_get_peak_usage () con "utilizzo reale"


93

Se l' real_usageargomento è impostato su truePHP DOCS diciamo che otterrà la dimensione reale della memoria allocata dal sistema. In tal caso falseotterrà la memoria segnalata daemalloc()

Quale di queste 2 opzioni restituisce il max. memoria allocata rispetto al valore limite di memoria in php.ini?

Voglio sapere quanto è stato vicino lo script a raggiungere quel limite.


8
Vorrei indicarvi una presentazione di Julien Pauli su youtube.com/watch?v=sm1HUrnsxLI per la conferenza php uk 2013, dove parla di come funziona la memoria all'interno di PHP.
mpratt

Risposte:


137

Ok, proviamo questo usando un semplice script:

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
}

Produzione:

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

Sembra che l'utilizzo reale sia la memoria allocata dal sistema, che sembra essere allocata in bucket più grandi di quelli attualmente necessari per lo script. (Immagino per motivi di prestazioni). Questa è anche la memoria utilizzata dal processo php.

L' $real_usage = falseutilizzo è l'utilizzo della memoria effettivamente utilizzato nel tuo script, non la quantità effettiva di memoria allocata dal gestore della memoria di Zend.

Leggi questa domanda per ulteriori informazioni.

In breve: per ottenere quanto sei vicino al limite di memoria, usa $real_usage = true


5
Il motore Zend alloca la memoria in blocchi da 256K. Il valore di "utilizzo reale" è la somma di tutti questi blocchi. Che in realtà è il valore utilizzato per innescare l'errore di esaurimento della memoria: if (segment_size < true_size || heap->real_size + segment_size > heap->limit) { /* Memory limit overflow */.
Cleong

2
Il valore "non reale" è la somma del numero di byte richiesti dalle chiamate a emalloc(più i byte per le intestazioni e l'allineamento della memoria). Non riflette la memoria sprecata a causa di blocchi che non si adattano allo spazio rimanente nei segmenti già allocati. Se modifichi il tuo esempio per allocare (1024 * 256) byte e un limite di 2 M, la differenza di due diventerà più evidente.
Cleong

@Niko, perché hai usato memory_get_peak_usage invece di memory_get_usage? Non dovremmo gc_disable () e usare memory_get_usage per ottenere un risultato più accurato?
Pacerier

@Pacerier la domanda era di avvicinarsi al limite della sceneggiatura - perché quel picco ha senso direi
Niko Sams

4
Come ha spiegato @cleong, questa risposta è effettivamente sbagliata, nonostante tutti i voti positivi. Il memory_get_usage(true)valore restituito da confrontare memory_limit. L'esempio fornito nella risposta è troppo semplice in quanto non c'è memoria "sprecata". Quello che succede è che la memoria allocata "reale" deve essere aumentata da "1 MiB" a "1,25 MiB" e questo è ciò che fa scattare l'errore fatale Ho uno script batch complesso con limite di memoria di 120 MiB che ha una memoria allocata "non reale" di soli "80 MiB" quando viene interrotto perché la memoria allocata "reale" raggiunge il limite.
Martin Prikryl

36

introduzione

Dovresti usare memory_get_usage(false)perché quello che vuoi è la memoria usata non la memoria allocata.

Qual è la differenza

Il vostro Google Mailpotrebbe avere assegnato 25MBdi archiviazione per voi, ma ciò non significa che sia quello che avete utilizzato al momento.

Questo è esattamente ciò che diceva il documento PHP

Impostalo su TRUE per ottenere la dimensione reale della memoria allocata dal sistema. Se non impostato o FALSE viene riportata solo la memoria utilizzata da emalloc ().

Entrambi gli argomenti restituiscono la memoria allocata rispetto al limite di memoria, ma la differenza principale è:

memory_get_usage(false)dare la memoria utilizzata da emalloc()while memory_get_usage(true)restituisce milestone che può essere dimostrata qui Memory Mile Store

Voglio sapere quanto è stato vicino lo script a raggiungere quel limite.

Ciò richiederebbe un po 'di matematica e potrebbe funzionare solo in loop o casi d'uso specifici. Perché l'ho detto?

Immaginare

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.

Per quanto ne so, l'unico modo in cui posso controllare la memoria utilizzata per una variabile o una sezione specifica di PHP è:

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

Vedere la spiegazione , ma se ci si trova in un ciclo o in una funzione ricorsiva è possibile utilizzare il massimo utilizzo della memoria per stimare in modo sicuro quando verrà raggiunto il peek di memoria.

Esempio

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
}

Produzione

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

Dimostrazione dal vivo

Questo potrebbe ancora fallire

Potrebbe non riuscire perché dopo if ($percentage > $peekPoint) { questo ancora aggiungere per fare attività aggiuntive consuma anche memoria

        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.

Conclusione

Non è una soluzione perfetta, ma controlla la memoria a intervalli e se supera la sbirciatina (ad esempio il 90%) exitimmediatamente e lascia le cose fantasiose


L' memory_limitopzione riguarda l'heap? o pila?
Yousha Aleayoub

cosa succede se ho due script in parallelo o molte richieste, la funzione memory_get_usage () restituisce la memoria utilizzata per tutti quegli script eseguiti nello stesso tempo o solo lo script vero e proprio?
Mohammed Yassine CHABLI

7

real_usagefalse segnala l'utilizzo utilizzato dallo script . Questo sarà il più accurato dei due.

real_usagetrue riporta la memoria allocata allo script. Questo sarà il più alto dei due.

Probabilmente lo userei truese stessi provando a confrontare, poiché il tuo script non verrebbe mai assegnato più del limite di memoria e continuerebbe a essere eseguito fintanto che (più tutti gli altri script) non supera tale utilizzo.


1
È esattamente l'opposto: falseè la memoria utilizzata dallo script , trueè la memoria allocata .
Benjamin

1
@ Benjamin Sì, non sono sicuro del motivo per cui ho sbagliato così ciecamente. Umm, fisso.
Glitch Desire

2

come per PHP memory_get_usage

real_usage

Impostalo su TRUE per ottenere la memoria totale allocata dal sistema, comprese le pagine inutilizzate. Se non impostato o FALSE viene riportata solo la memoria utilizzata.

quindi per ottenere la memoria utilizzata dal tuo script dovresti usare memory_get_usage () poiché real_usage di default è false.

se vuoi ottenere la memoria allocata dal sistema ma non ti interessa quanta è stata effettivamente utilizzata, usa 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
Benvenuto in Stackoverflow! potresti dirci qual è la risposta? Non solo il codice, ma anche come hai capito come risolvere la domanda. Grazie!
Gilles Heinesch

Sebbene la tua risposta possa fornire alcune informazioni potenzialmente utili, non è pertinente alla domanda che viene posta. Potresti spiegare in che modo la tua risposta si collega alla domanda che ti viene posta.
Moritur
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.