2012-04-20 3 views
0

私はかなり長いメモリ集中ループを持っています。私のサーバーは実行の時間制限を設けているため、またはメモリ不足のため、一度に実行することはできません。どのようにして、本当に長いメモリ集約ループをより小さなチャンクに分割するのですか?

このループを小さな塊に分割したいと考えています。

ループを小さなチャンクに分割し、新しい開始条件でスクリプトをリロードするための場所ヘッダーを設定することを考えました。

MY OLD SCRIPT(擬似コード。私は以下の欠点を承知している)

for($i=0;$i<1000;$i++) 
{ 
    //FUNCTION 
} 

MY NEW SCRIPTしかし

$start=$_GET['start']; 
$end=$start+10; 

for($i=$start;$i<$end;$i++;) 
{ 
    //FUNCTION 
} 

header("Location:script.php?start=$end"); 

、私の新しいスクリプトは、数回の反復のために正常に実行され、その後、Iサーバーエラーが発生する「リダイレクトが多すぎます」

方法はありますか?誰かがより良い戦略を提案できますか?

私は共有サーバー上にあるため、メモリ割り当てやスクリプト実行時間を増やすことはできません。

私はPHPソリューションを希望します。

ありがとうございました。

+0

。もっとコードを投稿できますか? – Jack

+0

PHPはガベージコレクションで本当にうんざりです。最近、(新しいGCライブラリを含む)ベースコードの改善や提案がたくさんありますが、私はそれらをすべて手に入れましたが、いくつかのケースでは、PHPがメモリをクリアしません。またはあなたが眠る。与えられた様々な答えを試してみてください。しかし、何も動かなければ、あなたは頭を壁に打つかもしれないことに注意してください。 – Anthony

+0

ループにSQLクエリが含まれていますか? – denil

答えて

0

まず、ループ内で何をしているのかわからなくても、実際に問題を解決するための最良のアプローチを教えてください。しかし、本当に長い時間がかかるものを実行したいのであれば、私の提案はcronジョブを設定して、一度に小さな部分を釘付けにすることです。スクリプトは停止した場所でログを記録し、次回の起動時にどこから開始するかをログで確認できます。


編集:あなたはcronのに対して死んでセットされている、とあなたはユーザーエクスペリエンスについてあまり心配していない場合は、あなたがこれを行うことができます:

上記のcronジョブへのページのロードが類似してみましょう。何秒も繰り返した後を除いて、スクリプトを停止します。リフレッシュメタタグまたはjavascriptリフレッシュを表示します。タスクが完了するまでこれを行います。

for($i=$start;$i<$end;$i++;) 
{ 
    $data_holder[] = "adding my big data chunks!"; 
    if($i % 5 == 1){ 
    //function to process data 
    process_data($data_holder); // process that data like a boss! 
    unset($data_holder); // This frees up the memory 
    } 
} 

// Now pick up the stragglers of whatever is left in the data chunk 
if(count($data_holder) > 0){ 
    process_data($data_holder); 
} 

あなたはを反復処理し続けることができますこの方法:私は何かの上に多くの多くの時間を反復する必要があり、それはデータのまともな量を持っている場合

+0

ありがとうTom、ループ内のスクリプトは問題ではありません。それはまったく何でもかまいません。重要なのは、それが本質的に時間とメモリを大量に消費することであり、貧弱な設計ではないということです。このアプリケーションでは、cronジョブが残念な場合があります。このスクリプトは、私のサーバー構成標準によってのみ時間とメモリを消費します。実行には2〜3分かかります。ヘッダーを次のブロックのリンクに変更して40回だけクリックするだけで、便利に自動的に実行できるようにしたいと考えています。 – Matt

+0

メタリフレッシュ/ javascriptの更新は自動的に行われます。これが欲しいと思わない場合は、Clay Hinsonが述べたようにフォークを調べてください。 – teynon

0

は一般的に、私のような「遅延ロード」タイプのアプリケーションを使用しますあなたのデータが、あなたの記憶を詰まらせることはありません。チャンクで作業し、データの設定を解除したり、チャンクで作業したり、データを設定解除するなどして、メモリを防ぐことができます。実行時間までは、どれくらいの時間を要しているか/スクリプトの効率性によって決まります。

基本的な前提 - 「メモリの問題を避けるために、データを小規模な塊で処理する。デザインを簡単にしておくことが簡単です」

+0

乾杯、これは間違いなくメモリの問題を解決するのに役立ちます。しかし、いくつかのケースでは、私はまだスクリプトの実行期限に問題があります。 – Matt

+0

@Matt、 'set_time_limit(0);'をmodulus if文にプラグインしてみてください。実行時間を変更することはできないかもしれませんが、実行時間が始まったと思うようにすることができます。アップ助言が有益であることは歓迎されています、それが最も適用可能/有用である場合に回答として選択するとより感謝します;) – Blake

0

ループ内に条件を入れて100回の繰り返しごとにスリープ状態にするのはどうでしょうか?

for ($i = 0; $i < 1000; $i++) 
{ 
    if ($i % 100 == 0) 
     sleep(1800) //Sleep for half an hour 
} 
0

あなたは、おそらく仕事をするためにforking child processesに見てみたいです。これらの子プロセスは、親プロセスが複数の子プロセスを起動する間に、自分のメモリ空間内の小さなチャンクで作業を実行できます。これは一般的にはGearmanによって処理されますが、これはなくても実行できます。

DealNews 'DevelopersサイトのForking PHPをご覧ください。子プロセスを生成する必要のあるコードを管理するためのライブラリとサンプルコードがあります。

2

「多すぎるリダイレクト」はブラウザエラーです。そのため、PHPソリューションでは、cURLまたは標準ストリームを使用して最初のページを読み込み、すべてのリダイレクトに従わせることがあります。ただし、タイムアウトの制限がない限り、マシンからこれを実行する必要があります(たとえば、CLIを使用して)

もう1つ考慮すべきことは、AJAXを使用することです。あなたのページのJavaScriptがあなたのスクリプトを実行し、スクリプトからの出力を集め、停止(計算の終了)または続行(Xから開始)のいずれかを決定します。このようにして、きれいなプログレスメーターを作成することもできます;-)

0

あなたが持っている制限によって、私はあなたが使っているアプローチがうまくいくと思います。あなたのブラウザがスマートで、直前のページをリダイレクトさせようとしていない可能性があります。それは無限ループを防止しようとしているかもしれません。

あなたは同じ(またはエイリアス)されている2つのスクリプトの間で前後にリダイレクト

  • を試みることができます。

  • 異なるブラウザです。

  • スクリプトでは、更新タグ付きのHTMLページを出力することができます。あなたのループが何をするのか知らずに言うのは難しい

    <meta http-equiv="refresh" content="1; url=http://example.com/script.php?start=xxx">

+0

ねえ、それは動作します。私はあなたがリフレッシュタグのURLを設定できることを知らなかった。私が望むほど流動的ではありませんが、それは仕事を完了させます。 – Matt

+0

私はむしろ「Fix the car。」と言うでしょう。 「しかし、もし私が崖からそれを押しても、まだ55になることができます! – Blake

+0

@ブレイク、私はあなたに同意しますが、 "あなたが持っている制限"と "しかし、それは仕事を完了します。 – bmb