9

我有一个大小为 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 如何在函数调用中处理大数组(在内存方面)?

4

2 回答 2

8

Here is a code to test:

<?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 />";


    ?>

and here is a output after i run it:

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

On stage 0 we can see that before array is created PHP is already using some space in memory. After creating first array (Stage 1) we can see a big change in memory usage as expected. But after calling function testnochanges function and creating $arrtest1 on Stage 2, we see that memory usage did not change a lot. It's because we did no changes to $arr, so $arrtest1 and $arr still are pointing to the same array. But on Stage 3, where we call testwithchanges function, and add an element to $arr PHP performs copy-on-write and returned array which is assigned to $arrtest2 now uses different part of memory and again we see a big grow of memory usage.

Dry conclusion: If you copy array to another array and do not change it, memory usage stays the same as both arrays are pointed to the same one. If you change the array PHP performs copy-on-write and, of course memory usage grows.

Good thing to read: Be wary of garbage collection, part 2.

于 2012-10-03T06:05:54.397 回答
2

The only way to really find out how your particular use case performs is to complete a benchmark (quick and dirty is fine). If you are having trouble with performance, you may want to look into SPL. For example, SplFixedArray can save memory when dealing larger arrays, granted you know the size beforehand. Also, newer versions of PHP handle garbage collection much better than previous versions, so upgrading may also help.

If you decide to run benchmarks, this will get you started (compares SPL with raw arrays): https://github.com/elazar/spl-benchmarks

于 2012-10-03T06:06:00.733 回答