具有大静态数组的PHP递归函数

时间:2013-07-25 20:50:34

标签: php recursion

我有一个像这样的爬虫功能:

function crawl_page($url) {
    static $j;
    echo "recur no:".++$j."\n";
    static $seen = array();

    if (isset($seen[$url]) ) {
        return;
    }

    $seen[$url] = true;

    // some more code


   foreach($links as $link) {
               $link .= '?start='.rand(1,300)*50; 
               crawl_page($link );
   }
   unset($links);

}

脚本在控制台中本地运行。里面的静态数组可能非常大,有数千个元素,它在内存中是否仍然是相同的数据,还是在每次新的递归调用完成后被复制?在2000或3000次重复之后,php进程太大了,内存超过1 GB并最终崩溃。似乎每次递归都使用了太多的内存。是什么原因?

2 个答案:

答案 0 :(得分:0)

使用简单的脚本进行测试

function func($iteration = 0) {
        if ($iteration++ == 3) return;
        print "\n$iteration\n";
        var_dump(memory_get_usage());
        static $var = array();
        var_dump(memory_get_usage());
        $var[] = str_repeat("byte", 100000);
        var_dump(memory_get_usage());
        func($iteration);
}

func();

给出:

1
int(632976)
int(632976)
int(1033232)

2
int(1033312)
int(1033312)
int(1433568)

3
int(1433648)
int(1433648)
int(1833904)

所以,我们看到了什么:内存使用量仅在插入时有所不同,但使用static $var;并没有真正改变内存。

结论

它必须只是你的数组大小,临时结果等让你的内存超过,但静态数组只花费一次内存(=它没有在每个函数调用中复制)。

答案 1 :(得分:0)

这部分代码我有点困惑:

 $link .= '?start='.rand(1,300)*50; 

这将使每个链接的多个版本。如果其中一个页面使用它自己的链接来建立自己的链接,那么你自己就会有一个无限循环:

$link == '/', result: self: '/', crawl_page('/?start=50');
$link == '/?start=50', self: '/?start=50', result: crawl_page('/?start=50?start=200');
...

也可能是页数乘以在0到299之间命中一个数字的平均数两次会因阵列中包含太多元素而耗尽内存。