始于群友提出的一个问题
<?php
$m1 = memory_get_usage();
echo 'm1:' . $m1;
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
echo PHP_EOL;
$m2 = memory_get_usage();
echo 'm2:' . $m2;
$arr2 = $arr1;
echo PHP_EOL;
echo 'm2-m1:' . ($m2 - $m1);
echo PHP_EOL;
$m3 = memory_get_usage();
echo 'm3:' . $m3;
echo PHP_EOL;
echo 'm3-m2:' . ($m3 - $m2);
$arr3 = [];
foreach ($arr2 as $key => $value) {
$arr3[] = $value;
}
// unset($m1,$m2);
$m4 = memory_get_usage();
echo PHP_EOL;
echo 'm4:' . $m4;
echo PHP_EOL;
echo 'm4-m3:' . ($m4-$m3);
这段代码的输出如下,为什么(m4-m3)比(m2-m1)少32字节?
m1:388416
m2:27651488
m2-m1:27263072
m3:27651488
m3-m2:0
m4:54914528
m4-m3:27263040
分析
$m1和$m2之间,除了echo输入,只做了一件事。给$arr1填充1000000个元素。
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i); // 销毁循环变量
$m3和$m4之间,除了echo输入,也只做了一件事。给$arr1填充1000000个元素。
$arr3 = [];
foreach ($arr2 as $key => $value) { // $arr2是$arr1的引用
$arr3[] = $value;
}
我们化简一下这段代码,把不相关元素都去掉。$m3和$m4之间,使用$arr1做数据源.
$m1 = memory_get_usage();
echo 'm1:' . $m1 . PHP_EOL;
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
$m2 = memory_get_usage();
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
$arr3 = [];
foreach ($arr1 as $key => $value) {
$arr3[] = $value;
}
$m3 = memory_get_usage();
echo 'm3-m2:' . ($m3-$m2) . PHP_EOL;
这段代码输出如下,和原始代码等效。
λ php index.php
m1:387336
m2-m1:27263072
m3-m2:27263040
进一步化简,把所有echo移到尾部
$m1 = memory_get_usage();
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
$m2 = memory_get_usage();
$arr3 = [];
foreach ($arr1 as $key => $value) {
$arr3[] = $value;
}
$m3 = memory_get_usage();
echo 'm1:' . $m1 . PHP_EOL;
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
echo 'm3-m2:' . ($m3-$m2) . PHP_EOL;
输出结果,两次内存用量相等了,问题不存在了。
λ php index.php
m1:387336
m2-m1:27263040
m3-m2:27263040
所以这32字节多在echo上。我们在m1和m2,m2和m3之间增加echo试试看。
test 1: m1后增加echo
$m1 = memory_get_usage();
echo "xxxxxxx" . PHP_EOL; // 增加echo
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
$m2 = memory_get_usage();
$arr3 = [];
foreach ($arr1 as $key => $value) {
$arr3[] = $value;
}
$m3 = memory_get_usage();
echo 'm1:' . $m1 . PHP_EOL;
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
echo 'm3-m2:' . ($m3-$m2) . PHP_EOL;
结果
m1:387400
m2-m1:27263072 // 多了32
m3-m2:27263040
test 2: m2后增加echo
$m1 = memory_get_usage();
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
$m2 = memory_get_usage();
echo "xxxxxxx" . PHP_EOL; // 增加echo
$arr3 = [];
foreach ($arr1 as $key => $value) {
$arr3[] = $value;
}
$m3 = memory_get_usage();
结果
m1:387400
m2-m1:27263040
m3-m2:27263072 // 多了32
test 3: m1和m2一起加echo
$m1 = memory_get_usage();
echo "xxxxxxx" . PHP_EOL;
$arr1 = [];
for($i = 0; $i < 1000000; $i++){
$arr1[] = $i;
}
unset($i);
$m2 = memory_get_usage();
echo "xxxxxxx" . PHP_EOL;
$arr3 = [];
foreach ($arr1 as $key => $value) {
$arr3[] = $value;
}
$m3 = memory_get_usage();
echo 'm1:' . $m1 . PHP_EOL;
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
echo 'm3-m2:' . ($m3-$m2) . PHP_EOL;
结果
m1:387400
m2-m1:27263072 // 多了32
m3-m2:27263040
test4 echo数据量和内存增量有什么关系
echo 1字节
$m1 = memory_get_usage();
echo str_repeat("x",1) . PHP_EOL;
$m2 = memory_get_usage();
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
结果
m2-m1:32
echo 10020字节
$m1 = memory_get_usage();
echo str_repeat("x",10020) . PHP_EOL;
$m2 = memory_get_usage();
echo 'm2-m1:' . ($m2-$m1) . PHP_EOL;
结果
m2-m1:32
内存增量都是32字节
在网上试了几个php sandbox,发现每个版本php内存增量是不一样的。
总结
- 首次echo会使内存用量增加,仅首次会增加
- 内存用量增加32字节,不管echo内容是多少字节。
- 不同版本php字节数会不同
本机测试环境
PHP 7.2.10 (cli) (built: Sep 13 2018 01:01:10) ( ZTS MSVC15 (Visual C++ 2017) x86 )
不错,过来支持一下