我有一个大小为5 MB的数组,我将它传递给函数到函数(我不是通过引用传递)
foo( $arr );
function foo( $arr ) {
....
bar( $arr );
....
}
function bar( $arr ) {
....
test( $arr );
....
}
function test( $arr ) {
....
test2( $arr );
....
}
PHP默认情况下通过值(值的副本)将数组值传递给函数。
我的问题是,如果这个数组值被传递给100个函数调用,PHP会消耗100 x 5 MB=500 MB的内存吗?
PHP如何处理函数调用中的大数组(内存方面)?
这里有一个要测试的代码:
<?php
function testnochanges($arr1){
foreach($arr1 as $val){
//
}
return $arr1;
}
function testwithchanges($arr1){
$arr1[] = 1;
return $arr1;
}
echo "Stage 0: Mem usage is: " . memory_get_usage() . "<br />";
for ($i = 0; $i < 100000; ++$i) {
$arr[] = rand();
}
echo "Stage 1 (Array Created): Mem usage is: " . memory_get_usage() . "<br />";
$arrtest1 = testnochanges($arr);
echo "Stage 2 (Function did NO changes to array): Mem usage is: " . memory_get_usage() . "<br />";
$arrtest2 = testwithchanges($arr);
echo "Stage 3 (Function DID changes to array): Mem usage is: " . memory_get_usage() . "<br />";
?>
这是我运行后的输出:
Stage 0: Mem usage is: 330656
Stage 1 (Array Created): Mem usage is: 8855296
Stage 2 (Function did NO changes to array): Mem usage is: 8855352
Stage 3 (Function DID changes to array): Mem usage is: 14179864
在阶段0中,我们可以看到在创建数组之前,PHP已经在使用内存中的一些空间。在创建第一个数组(Stage 1)之后,我们可以看到内存使用率如预期的那样发生了巨大变化。但是,在Stage2上调用函数testnochanges
函数并创建$arrtest1
之后,我们发现内存使用情况没有太大变化。这是因为我们没有更改$arr
,所以$arrtest1
和$arr
仍然指向同一个数组。但是在阶段3,我们调用testwithchanges
函数,并向$arr
添加一个元素。PHP执行copy-on-write
,返回的分配给$arrtest2
的数组现在使用不同的内存部分,我们再次看到内存使用量的大幅增长。
枯燥的结论:如果将数组复制到另一个数组而不更改它,则内存使用率将保持不变,因为两个数组都指向同一个数组。如果您更改数组,PHP将执行copy-on-write
,当然内存使用量也会增加。
值得一读的是:警惕垃圾收集,第2部分。
真正了解特定用例执行情况的唯一方法是完成一个基准测试(快速而肮脏也没关系)。如果您在性能方面遇到问题,您可能需要了解SPL。例如,SplFixedArray
在处理较大的数组时可以节省内存,前提是您事先知道大小。此外,较新版本的PHP比以前的版本更好地处理垃圾收集,因此升级也可能有所帮助。
如果您决定运行基准测试,这将使您开始(将SPL与原始阵列进行比较):https://github.com/elazar/spl-benchmarks