0

多くのhtmlファイルからデータファイルを抽出しようとしています。高速にするために、DOM パーサーは使用しませんが、シンプルstrpos()です。約 200000 ファイルから生成すると、すべてがうまくいきます。しかし、より多くのファイル (300000) でそれを行うと、何も出力されず、この奇妙な効果が発生します。下の図を見てください。(上はCPUです)最初の(赤でマークされた)フェーズでは、出力ファイルサイズが大きくなり、すべて問題ないようです。その後、(オレンジ色でマークされた)ファイルサイズがゼロになり、メモリ使用量が増えています。(ハーフタイムに計算を再開したので、すべて2回です)

WAMP を使用していることを忘れていました。

変数の設定を解除したり、ループを関数に入れたり、文字列を連結する代わりに内破を使用したり、filegetcontents の代わりに fopen を使用したり、ガベージ コレクションも使用したりしました...

2期とは?私は記憶がありませんか?私が知らない制限はありますか (max_execution_time,memory_limit - 既に無視されています)? なぜこの小さなプログラムが大量のメモリを使用するのでしょうか?

処理

これがコードです。

$datafile = fopen("meccsek2b.jsb", 'w');
for($i=0;$i<100000;$i++){
    $a = explode('|',$data[$i]);
    $file = "data2/$mid.html";
    if(file_exists($file)){
        $c = file_get_contents($file);
        $o = 0;
        $a_id = array();
        $a_h = array();
        $a_d = array();
        $a_v = array();
        while($o = strpos($c,'<a href="/test/',$o)){
            $o = $o+15;
            $a_id[] = substr($c,$o,strpos($c,'/',$o)-$o);
            $o = strpos($c,'val_h="',$o)+7;
            $a_h[] = substr($c,$o,strpos($c,'"',$o)-$o); 
            $o = strpos($c,'val_d="',$o)+7;
            $a_d[] = substr($c,$o, strpos($c,'"',$o)-$o);
            $o = strpos($c,'val_v="',$o)+7;
            $a_v[] = substr($c,$o,strpos($c,'"',$o)-$o);        
        }
        fwrite($datafile,  
            $mid.'|'.
            implode(';',$a_id).'|'.
            implode(';',$a_h).'|'.
            implode(';',$a_d).'|'.
            implode(';',$a_v).
            PHP_EOL);       
    }
}
fclose($datafile);

Apache エラー ログ。(30日で期限切れ)

私は問題を見つけたと思います:

0 が返されたため、無限ループが発生しましたstrpos()。割り当てられたメモリ サイズは、例外が発生するまで増加していました。

PHP Fatal error:  Out of memory 

Ensino のメモは、コマンド ラインの使用について非常に役に立ち、最終的にこの質問にたどり着きました。

4

3 に答える 3

0

コマンドラインからスクリプトを実行することを検討する必要があります。このようにして、エラー ログを掘り下げずにエラーをキャッチできます。
さらに、PHP マニュアルに記載されているように、strpos関数はブール値の FALSE を返す場合がありますが、FALSE と評価される非ブール値を返す場合もあるため、この関数の戻り値をテストする正しい方法は、次!==演算子を使用することです。

while (($o = strpos($c,'<a href="/test/',$o)) !== FALSE){
...
}
于 2013-08-25T15:48:47.590 に答える
0

CPU スパイクは、PHP がガベージ コレクションを行っていることを意味する可能性が最も高いです。より大きなメモリ使用量を犠牲にしてある程度のパフォーマンスを得たい場合は、 gc_disable() でガベージ コレクションを無効にすることができます。

コードを見ると、大きなファイルを読み込んでいるポイントに到達したと思います。PHP は、file_get_contentsガベージ コレクションを実行してそのコンテンツを格納できるようにするためにメモリを解放する必要があることを認識しています。

これに対処する最善の方法は、ファイル全体をメモリに保持するのではなく、ファイルを継続的に読み取り、チャンクごとに処理することです。

于 2013-08-23T13:55:06.543 に答える