2013-04-01 73 views
72

如果real_usage參數設置爲true,那麼PHP DOCS會說它會從系統中獲得實際分配的內存大小。如果它是false它將得到內存報告emalloc()memory_get_peak_usage()with「real usage」

這兩個選項中的哪一個返回最大值。內存分配相對於php.ini中的內存限制值嗎?

我想知道劇本到底有多接近。

+8

我想你點爲PHP英國會議2013年,他在那裏談論存儲器內部是PHP是如何工作的文稿由朱利安保利http://www.youtube.com/watch?v=sm1HUrnsxLI。 – mpratt

+0

也看到http://stackoverflow.com/a/7234026/632951 – Pacerier

回答

96

好吧,讓測試此使用一個簡單的腳本:

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

+2

Zend引擎以256K塊分配內存。 「實際使用」值是所有這些塊的總和。這實際上是用來觸發內存耗盡錯誤的值:'if(segment_size real_size + segment_size> heap-> limit){*內存溢出限制* /'。 – cleong

+1

「not real」值是通過調用「emalloc」請求的字節數(加上字節和內存對齊字節)的總和。它並不反映由於塊不符合已分配段中剩餘的空間而造成的內存浪費。如果您將示例更改爲分配(1024 * 256)字節和2M限制,則兩者之間的差異將變得更加明顯。 – cleong

+0

@Niko,你爲什麼使用memory_get_peak_usage而不是memory_get_usage?我們不應該使用gc_disable()並使用memory_get_usage來獲得更準確的結果嗎? – Pacerier

6

real_usage虛假報告使用您的腳本使用。這將是兩者中更準確的。

real_usage true報告內存已將分配給您的腳本。這將是兩者中較高的。

如果我試圖比較,我可能會使用true,因爲你的腳本永遠不會被分配超過內存限制,並且只要它(加上所有其他腳本)沒有超過這個用法就會繼續運行。

+4

不,我的腳本顯示,real_usage真正的高 –

+1

這是完全相反的:'FALSE'是腳本*使用*內存,'真'是內存*分配*。 – Benjamin

+1

@Benjamin是的,不知道爲什麼我這麼盲目的錯誤。恩,固定。 –

29

介紹

你應該使用memory_get_usage(false),因爲你想要的是內存使用的不是內存分配。

請告訴我差

Google Mail可能已分配的存儲你的25MB,但它並不意味着是你目前使用的是什麼。

這正是PHP的文檔是說

Set this to TRUE to get the real size of memory allocated from system. If not set or FALSE only the memory used by emalloc() is reported.

兩個參數將內存分配相對返回內存限制,主要的區別是:

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.

結論

它不是一個完美的解決方案,但在間隔檢查內存,如果它超過PEEK(如90%)exit瞬間,並留下了花哨的東西

1

按照PHP memory_get_usage

real_usage

Set this to TRUE to get total memory allocated from system, including unused pages. If not set or FALSE only the used memory is reported.

所以要得到你的腳本中使用的內存,你應該使用memory_get_usage()作爲默認real_usage是假的。

,如果你想獲得由系統分配的內存,但不關心有多少實際使用,使用memory_get_usage(真);