簡體   English   中英

減少數組和SplFixedArray的內存使用量

[英]Decreasing memory usage for array and SplFixedArray

我在array()SplFixedArray()之間做了一些基准測試,我遇到了奇怪的行為。 首先,看看我的簡單測試(它實際上只是來自互聯網的編輯版本,對不起,我現在找不到原始資料):

function formatMemoryUsage($usage) {
   $unit = array(' B', 'kB', 'MB', 'GB', 'TB');
   $factor = floor((strlen($usage) - 1) / 3);

   return sprintf('%.2f %s (%d bytes) ', $usage / pow(1024, $factor), $unit[$factor], $usage);
}

for($size = 1000; $size < 100000; $size *= 2) { 
   echo PHP_EOL . '> Testing size: ' . number_format($size) . PHP_EOL; 
   echo '   Array()' . PHP_EOL;

   for($s = microtime(true), $m = memory_get_usage(true), $container = Array(), $i = 0; $i < $size; $i++) $container[$i] = null; 
      echo '      - Write         - time   : ' . str_pad(microtime(true) - $s, 20, '0') . '     - memory: ' . formatMemoryUsage(memory_get_usage(true) - $m) . PHP_EOL; 

   $s = microtime(true); 
   foreach ($container as $key => $value) {
      $void = $value;
   }
   echo '      - Read          - time   : ' . str_pad(microtime(true) - $s, 20, '0') . PHP_EOL;

   unset($container);

   echo '   SplFixedArray()' . PHP_EOL;

   for($s = microtime(true), $m = memory_get_usage(true), $container = new SplFixedArray($size), $i = 0; $i < $size; $i++) $container[$i] = null; 
   echo '      - Write         - time   : ' . str_pad(microtime(true) - $s, 20, '0') . '     - memory: ' . formatMemoryUsage(memory_get_usage(true) - $m) . PHP_EOL; 

   $s = microtime(true); 
   foreach ($container as $key => $value) {
      $void = $value;
   }
   echo '      - Read          - time   : ' . str_pad(microtime(true) - $s, 20, '0') . PHP_EOL; 

   unset($container);
} 

結果有點預期 - SplFixedArray()寫入速度更快,讀取速度稍慢。 當我在前一個的unset()之后放入另一個相同的SplFixedArray()測試時,事情開始變得奇怪,請參閱輸出:

> Testing size: 64,000
   Array()
      - Write         - time   : 0.009041070938110400     - memory: 7.50 MB (7864320 bytes) 
      - Read          - time   : 0.004010915756225600
   SplFixedArray()
      - Write         - time   : 0.004639148712158200     - memory: 1.75 MB (1835008 bytes) 
      - Read          - time   : 0.005971908569335900
   SplFixedArray()
      - Write         - time   : 0.005653858184814500     - memory: 1.50 MB (1572864 bytes) 
      - Read          - time   : 0.006288051605224600

為什么第二次測試使用的內存少於第一次? 嘿,我嘗試添加下一個測試,並:

> Testing size: 64,000
   Array()
      - Write         - time   : 0.008963823318481400     - memory: 7.50 MB (7864320 bytes) 
      - Read          - time   : 0.004142045974731400
   SplFixedArray()
      - Write         - time   : 0.005026102066040000     - memory: 1.75 MB (1835008 bytes) 
      - Read          - time   : 0.005756139755249000
   SplFixedArray()
      - Write         - time   : 0.004483938217163100     - memory: 1.50 MB (1572864 bytes) 
      - Read          - time   : 0.005591869354248000
   SplFixedArray()
      - Write         - time   : 0.004633903503418000     - memory: 1.25 MB (1310720 bytes) 
      - Read          - time   : 0.005697011947631800

所以我當然會嘗試添加越來越多的內容,然后在512 kB之后再減少幾次。 我的問題在這里是顯而易見的: 如何可能以及為什么當我取消設置上一個對象並創建新對象時,使用的內存較低? 它也適用於普通的array()

如果我們想了解這一點,我們需要進入引擎。 更好:在Zend / zend_alloc.c(Zend Memory Manager)中

內存管理器分配的內存被分成256 KB的塊。

釋放SPLFixedArray后, 釋放第一個連續的內存塊 始終存在256 KB(某些變量)的塊,然后累積。 (作為OS分配的內存的下一個工作將與此內存塊相鄰)

然后將此內存段標記為空閑,並在可能的情況下下次使用,而不是從OS分配新內存。 (如果需要,還會附加一些內存)

但由於至少有一個256 KB的塊總是被釋放,我們總會注意到256 KB的差異。


當你想測量內存使用量時,我真的會使用memory_get_usage(false)因為它表明PHP(≠Zend)需要多少內存。 (對memory_limit ini設置唯一重要的事情)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM