2012-10-03 46 views
7

我有大小5 MB的阵列,我将它传递给功能的功能(我不是通过引用传递它PHP阵列性能 - 存储器明智

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如何在函数调用中处理大数组(在内存中)?

+0

不能告诉你,但你可能要考虑的迭代器和foreach循环,你可能这种方式有更好的内存消耗。 –

+1

你可以通过http://www.php.net/manual/en/function.memory-get-usage.php找到。 –

回答

6

下面是测试代码:

<?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是已经在内存中使用了一些空间。在创建第一个阵列后(阶段1),我们可以看到预期的内存使用量有很大变化。但在调用功能testnochanges函数并在阶段2上创建$arrtest1后,我们看到内存使用情况没有太大变化。这是因为我们没有更改$arr,所以$arrtest1$arr仍然指向相同的阵列。但是在阶段3,我们调用testwithchanges函数,并添加一个元素到$arr PHP执行copy-on-write和返回的数组被分配到$arrtest2现在使用不同的内存部分,我们再次看到内存使用量的增长。

结论:如果将数组复制到另一个数组并且不更改它,内存使用率保持不变,因为两个数组都指向同一个数组。如果你改变数组PHP执行copy-on-write,当然内存使用增长。

好东西阅读:Be wary of garbage collection, part 2

+1

除此之外,http://blog.golemon.com/2007/01/youre-being-lied-to.html是对幕后情况的解释,如果您有兴趣的话。 –

+0

有趣......记忆只有在我们改变时才会被分配,好的学习点。谢谢 !。 – SuVeRa

+0

@SuVeRa我用新的代码和新的测试编辑答案,以确保它与函数完全一致。 – F0G

2

真正了解您的特定用例执行情况的唯一方法是完成一个基准测试(快速且肮脏就好)。如果您遇到性能问题,您可能需要查看SPL。例如,SplFixedArray可以在处理较大的数组时节省内存,并提前知道该大小。此外,较新版本的PHP处理垃圾收集比先前版本好得多,因此升级也可能有所帮助。

如果你决定运行的基准,这将让你开始(用比较原始阵列SPL): https://github.com/elazar/spl-benchmarks

+0

好的,谢谢! – SuVeRa