memory_get_peak_usage () "gerçek kullanım" ile


94

Eğer real_usageargüman truePHP DOCS'ye ayarlanmışsa , sistemden ayrılan belleğin gerçek boyutunu alacağını söyler. Eğer öyleyse false, hafızayı rapor edecekemalloc()

Bu 2 seçenekten hangisi maks. php.ini içindeki bellek sınır değerine göre ayrılmış bellek?

Komut dosyasının bu limite ne kadar yaklaştığını bilmek istiyorum.


9
Php uk konferansı 2013 için Julien Pauli youtube.com/watch?v=sm1HUrnsxLI tarafından, belleğin PHP içinde nasıl çalıştığından bahsettiği bir sunuma işaret etmek istiyorum .
mpratt

Yanıtlar:


139

Tamam, bunu basit bir komut dosyası kullanarak test edelim:

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
}

Çıktı:

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

Görünüşe göre gerçek kullanım, sistemden ayrılan bellektir - bu, şu anda komut dosyası tarafından ihtiyaç duyulandan daha büyük bölümlere ayrılmış gibi görünüyor. (Sanırım performans nedenleriyle). Bu aynı zamanda php işleminin kullandığı bellektir.

$real_usage = falseKullanım aslında alfabenizde kullanılan bellek kullanımı değil, zerdüştlerin hafıza yöneticisi tarafından ayrılan bellek fiili miktarıdır.

Daha fazla bilgi için bu soruyu okuyun .

Kısacası: hafıza sınırına ne kadar yaklaştığınızı görmek için $real_usage = true


5
Zend motoru, belleği 256K yığın halinde ayırır. "Gerçek kullanım" değeri, tüm bu parçaların toplamıdır. Bu aslında hafıza tükenme hatası tetiklemek için kullanılan değerdir: if (segment_size < true_size || heap->real_size + segment_size > heap->limit) { /* Memory limit overflow */.
cleong

2
"Gerçek değil" değeri, çağrıların talep ettiği bayt sayısının toplamıdır emalloc(artı başlıklar ve bellek hizalaması için bayt). Önceden tahsis edilmiş segmentlerde kalan boşluğa sığmayan bloklar nedeniyle boşa harcanan belleği yansıtmaz. Örneğinizi (1024 * 256) bayt ve 2M sınırı ayıracak şekilde değiştirirseniz, ikisinin farkı daha belirgin hale gelecektir.
cleong

@Niko, memory_get_usage yerine neden memory_get_peak_usage kullandın? Daha doğru bir sonuç elde etmek için gc_disable () ve memory_get_usage kullanmamız gerekmez mi?
Pacerier

O tepe markaları söyleyebilirim anlamda için - Soru senaryo ne kadar yakın limite almak oldu @Pacerier
Niko Sams

4
@Cleong'un açıkladığı gibi, tüm olumlu oylara rağmen bu cevap aslında yanlış. Karşılaştırılması memory_get_usage(true)gereken dönüş değeri memory_limit. Yanıtta verilen örnek, "boşa harcanmış" bellek "olmadığı için çok basittir. Olan," gerçek "ayrılmış belleğin" 1 MiB "den" 1.25 MiB "ye yükseltilmesi gerektiğidir ve bu ölümcül hatayı tetikleyen şeydir. "Gerçek" ayrılmış bellek sınıra ulaştığı için iptal edildiğinde yalnızca "80 MiB" bellek "gerçek olmayan" ayrılmış belleğe sahip 120 MiB bellek sınırına sahip karmaşık bir toplu komut dosyam var.
Martin Prikryl

37

Giriş

Kullanmalısınız memory_get_usage(false)çünkü istediğiniz bellek ayrılmış bellek değil kullanılır.

Fark ne

Sizin için depolama alanı Google Mailtahsis etmiş olabilirsiniz, 25MBancak bu şu anda kullandığınız şeyin bu olduğu anlamına gelmez.

PHP belgesinin söylediği tam olarak buydu

Sistemden ayrılan gerçek bellek boyutunu almak için bunu TRUE olarak ayarlayın. Ayarlanmazsa veya YANLIŞ ise yalnızca emalloc () tarafından kullanılan bellek rapor edilir.

Her iki bağımsız değişken de bellek sınırına göre ayrılmış belleği döndürür, ancak temel fark şudur:

memory_get_usage(false)Burada gösterilebilecek olan emalloc()while memory_get_usage(true)return kilometre taşının kullandığı belleği verin Memory Mile Store

Komut dosyasının bu limite ne kadar yaklaştığını bilmek istiyorum.

Bu biraz matematik gerektirir ve yalnızca döngülerde veya belirli kullanım durumlarında işe yarayabilir. Neden böyle söyledim

Hayal etmek

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'nin bir değişken veya belirli bir bölümü için kullanılan belleği kontrol etmenin tek yolunu bildiğim kadarıyla:

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

Açıklamaya bakın , ancak bir döngü veya özyinelemeli işlev içindeyseniz, bellek zirvesine ne zaman ulaşılacağını güvenli bir şekilde tahmin etmek için maksimum bellek kullanımını kullanabilirsiniz.

Misal

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
}

Çıktı

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

Canlı Demo

Bu hala başarısız olabilir

Başarısız olabilir çünkü bundan sonra if ($percentage > $peekPoint) { hala ek görevler yapmak için ek olarak bellek de tüketir

        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.

Sonuç

Mükemmel bir çözüm değil, ancak aralıklı olarak belleği kontrol edin ve hızlı bir şekilde göz atıp aşmadığını (ör.% 90) exitve süslü şeyleri bırakın


memory_limityığın hakkında seçeneği? veya yığın?
Yousha Aleayoub

ya paralel olarak iki betiğim veya çok sayıda isteğim varsa, memory_get_usage () işlevi aynı anda yürütülen tüm bu betik için kullanılan belleği mi yoksa yalnızca gerçek betikleri mi döndürür?
Mohammed Yassine CHABLI

7

real_usagefalse komut dosyanızın kullandığı kullanımı bildirir . Bu, ikisinden daha doğru olacaktır.

real_usagetrue , betiğinize ayrılan belleği bildirir . Bu ikisinden yüksek olacak.

trueKarşılaştırmaya çalışsaydım muhtemelen kullanırdım , çünkü betiğiniz hiçbir zaman bellek sınırından daha fazla tahsis edilmeyecek ve kendisi (artı diğer tüm betikler) bu kullanımı aşmadığı sürece çalışmaya devam edecektir.


1
Tam tersi: falsekomut hafızadır kullanılan , truehafızadır tahsis .
Benjamin

1
@Benjamin Evet, neden bu kadar körü körüne yanlış anladığımı bilmiyorum. Düzeltildi.
Glitch Desire

2

PHP memory_get_usage'a göre

real_usage

Kullanılmayan sayfalar dahil olmak üzere sistemden ayrılan toplam belleği almak için bunu DOĞRU olarak ayarlayın. Ayarlanmazsa veya YANLIŞ ise, yalnızca kullanılan bellek rapor edilir.

bu yüzden betiğiniz tarafından kullanılan belleği elde etmek için, varsayılan real_usage false olduğundan memory_get_usage () kullanmalısınız.

sistem tarafından ayrılan belleği almak istiyor ancak gerçekte ne kadar kullanıldığını umursamıyorsanız, memory_get_usage (true) işlevini kullanın;


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'a hoş geldiniz! lütfen bize cevabın ne olduğunu söyler misiniz? Sadece kod değil, aynı zamanda soruyu nasıl çözeceğinizi nasıl anladığınızı da. Teşekkürler!
Gilles Heinesch

Cevabınız bazı potansiyel olarak yararlı bilgiler sağlayabilir ancak sorulan soru ile ilgili değildir. Cevabınızın sorulan soru ile nasıl bir ilgisi olduğunu açıklamak isteyebilirsiniz.
Moritur
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.