0

かなり長い、メモリを大量に消費するループがあります。サーバーに実行時間制限が設定されているか、メモリが不足しているため、一度に実行できません。

このループを小さなチャンクに分割したいと思います。

ループを小さなチャンクに分割し、ロケーションヘッダーを設定して、新しい開始条件でスクリプトをリロードするというアイデアがありました。

MY OLD SCRIPT(擬似コード。以下の欠点を認識しています)

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

私の新しいスクリプト

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

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

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

ただし、新しいスクリプトは数回の反復で正常に実行され、サーバーエラー「リ​​ダイレクトが多すぎます」が表示されます。

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

共有サーバーを使用しているため、メモリ割り当てやスクリプトの実行時間を増やすことができません。

PHPソリューションが欲しいのですが。

ありがとう。

4

6 に答える 6

2

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

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

于 2012-04-20T03:35:45.853 に答える
1

おそらく、作業を行うために子プロセスをフォークすることを検討したいと思うでしょう。これらの子プロセスは、親プロセスが複数の子プロセスを起動している間、独自のメモリ空間で小さなチャンクで作業を行うことができます。これは通常、Gearman によって処理されますが、なくても実行できます。

Dealnews の Developers サイトの Forking PHPを見てください。子プロセスを生成する必要があるコードを管理するのに役立つライブラリといくつかのサンプル コードがあります。

于 2012-04-20T03:29:22.877 に答える
0

まず、ループ内で何をしているのかを知らなければ、実際に問題を解決するための最善のアプローチを伝えるのは困難です。ただし、非常に長い時間がかかるものを実行したい場合は、cronジョブを設定して、一度に少しずつ実行することをお勧めします。スクリプトは停止した場所をログに記録し、次に起動したときに、開始する場所のログを読み取ることができます。


編集:cronに完全に反対していて、ユーザーエクスペリエンスについてあまり心配していない場合は、次のようにすることができます。

上記のcronジョブと同様にページをロードします。非常に多くの秒数または反復後を除いて、スクリプトを停止します。更新メタタグまたはJavaScript更新を表示します。タスクが完了するまでこれを行います。

于 2012-04-20T03:18:14.210 に答える
0

通常、何かを何度も反復する必要があり、データ量が適切な場合は、次のような「遅延ロード」タイプのアプリケーションを使用します。

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);
 }

そうすれば、データを反復処理し続けることができますが、メモリがいっぱいになることはありません。チャンクで作業してから、データの設定を解除し、チャンクで作業し、データの設定を解除するなどして、メモリを防ぐことができます。実行時間に関しては、それはあなたがしなければならない量/スクリプトがどれだけ効率的に書かれているかによって異なります。

基本的な前提 - 「メモリの問題を回避するために、データを小さなチャンクで処理します。高速に保つために、デザインをシンプルに保ちます。」

于 2012-04-20T03:20:43.100 に答える
0

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

for ($i = 0; $i < 1000; $i++)
{
    if ($i % 100 == 0)
        sleep(1800) //Sleep for half an hour
}
于 2012-04-20T03:24:37.647 に答える
0

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

あなたは試すことができます

  • 同一 (またはエイリアス) の 2 つのスクリプト間をリダイレクトします。

  • 別のブラウザ。

  • スクリプトにリフレッシュ タグを含む HTML ページを出力させる。

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

于 2012-04-20T04:01:16.997 に答える