我在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()
写作速度更快,阅读速度稍慢。当我在前一个SplFixedArray()
之后立即进行另一次unset()
测试时,事情开始变得奇怪,请参阅输出:
> 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()
。
答案 0 :(得分:2)
如果我们想了解这一点,我们需要进入引擎。更好:在Zend/zend_alloc.c (The Zend Memory Manager)内。
内存管理器分配的内存被分成256 KB的块。
释放SPLFixedArray后,only the first contiguous chunk of memory is freed。始终存在256 KB(某些变量)的块,然后累积。 (作为OS分配存储器的下一个工作,它将与该存储器块相邻)
此内存段然后是marked as free,并在可能的情况下下次使用,而不是从OS分配新内存。 (如有必要,附上一些记忆)
但由于至少有一个256 KB的块总是被释放,我们总会注意到256 KB的差异。
当你想测量内存使用时,我真的会使用memory_get_usage(false)
,因为它表明PHP(≠Zend)需要多少内存。 (唯一与memory_limit
ini设置相关的事物)