2

私はこのようなクローラー機能を持っています:

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 を超え、最終的にクラッシュします。各再帰が大量のメモリを使用しているようです。理由は何ですか?

4

2 に答える 2

0

私が少し困惑しているコードのこの部分:

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

これにより、各リンクの複数のバージョンが作成されます。これらのページの 1 つが独自のリンクを使用してそれ自体へのリンクを作成すると、無限ループが発生します。

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

また、0 から 299 までの 1 つの数値を 2 回ヒットした平均をページ数に掛けると、配列内の要素が多すぎるためにメモリが使い果たされる可能性もあります。

于 2013-07-25T22:13:24.840 に答える
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回しか消費しません(=すべての関数呼び出しでコピーされるわけではありません)。

于 2013-07-25T20:59:49.857 に答える