2

mod_perlで実行されているPerlスクリプトがあり、クライアントに大量のデータを、場合によっては長期間にわたって書き込む必要があります。私が観察する動作は、何かを印刷してフラッシュすると、バッファメモリが再利用されないことですrflush(これはOSによって再利用できないことを知っています)。

それはmod_perlの動作方法であり、定期的にバッファメモリを解放するように強制して、OSからより多くを取得する代わりに、新しいバッファに使用できるようにする方法はありますか?

明確にするために、私は自分でバッファを使用しておらず、コードにリークはありません。次の簡単な例を考えてみましょう。

  sub handler { 
     my $request = shift; 
     my $boundary = time; 
     $request->content_type("multipart/x-mixed-replace;boundary=\"$boundary\";"); 
     for (;;) { 
        $request->print("--$boundary\n"); 
        $request->print("Content-type: text/html; charset=utf-8;\n\n"); 
        $request->print("$data\n\n"); 
        $request->rflush;
     } 
     return Apache2::Const::OK; 
  } 

これはひどくリークし、私のリクエストは存続しているので、何日もアクティブになる可能性があります。

4

3 に答える 3

2

OSにメモリを返さないことは、perlインタプリタ自体の標準的な動作であり、mod_perl自体に固有のものではありません。共有メモリ(IIRCでは手動で割り当て/割り当て解除を処理します)を使用するか、プロセスを終了する以外に、perlメモリをホストOSに解放する方法を知りません。

変数をスコープ外に渡すと、perlそのメモリを他の変数に再利用できますが、OSには返されません。

編集:perl質問を読み直したところ、OSに解放しようとするのではなく、メモリを再利用できる ようにする方法を探しているだけであることがわかりました。その場合、myグローバルバッファーを早期に定義して永久に保持するのではなく、字句()変数を使用してそれらを可能な限り最小のスコープに限定することでうまくいくはずです。

于 2010-03-16T11:43:49.353 に答える
0

for(;;) ループが記述どおりに終了することはありません。これは、メモリ リークよりも悪い問題につながります。print メソッドは、おそらく要求レコードの一部として、ある程度のメモリを割り当てる必要があります。これは通常、要求がクリーンアップされるときに解放されます。これは、mod_perl2 または Apache2 内の C コードで発生しています。

これを回避するには、アプローチを再設計する必要があります。mod_perl ハンドラー内から長時間実行される応答を送信する代わりに、ProxyPass 設定を介して、応答を STDOUT に出力するプログラムにユーザーをリダイレクトします。(本質的には CGI スクリプトです。) スクリプトは、変数のスコープの制限について他の投稿者が言及した手法が機能する純粋な perl にすることができます。応答は引き続き Apache を通過しますが、リバース プロキシとして動作している場合、Apache には固定された一連のバッファがあり、バケット ブリゲードでデータをコピーします。大量のデータを通過するにもかかわらず、リバース プロキシ プロセスが多くのメモリを消費するのを見たことがありません。

于 2010-06-02T02:00:35.213 に答える
-1

バッファへの参照をすべて解放します。たとえば、次のように文字列をバッファとして使用していた場合

$buf = "really long string " . "and other methods that make it huger";
print SOMEWHERE $buf;
$buf = ""; # or undef $buf according to taste

以前に $buf が指していたストレージをフリー プールに戻す必要があります。

于 2010-03-16T05:23:33.600 に答える