6

私はColdFusionでデータベースロードスクリプトを作成しましたが、スクリプトのメモリがゆっくりと不足するという問題があります。各テーブルの読み込みを<cfthread>を使用して独自のスレッドに分割し、メモリが50%を下回ったときにガベージコレクターを呼び出しています(ガベージコレクターがメモリを占有しないように、gc()呼び出しの間隔を30秒にしてください) 。

スクリプトに必要なすべてのクエリを保持するCFCを作成しました。スクリプトは適切なCFC関数を呼び出し、クエリを返します。クエリの一部は2MBを超えています。アクティブなスレッドのメモリページの詳細ビューでサーバーモニターを見ると、クエリ変数をvarscopeして、最後に変数がスコープ外になったにもかかわらず、CFCがクエリのコピーをメモリに保持しているように見えます関数の。さらに、スレッドのメモリにクエリのコピーがあります。だから私はメモリ内のクエリの2つのコピーのように見えるものが残っています。これは本当に何が起こっているのですか?もしそうなら、どうすればメモリからクエリのコピーを1つ削除できますか?

4

2 に答える 2

11

ここには多くの潜在的な問題がありますが、私はあなたが考慮すべき最も重要なことのいくつかに下線を引くようにします:

  1. なぜスレッド?スレッドが必要ですか?おそらく自分の利益のためにいじりすぎている特定のポイントがあります。
  2. ガベージコレクションを手動で強制することは、必ずしも良い考えではありません。ガベージコレクションを自動的に実行するようにJVMを調整しますが、やりすぎないでください。ガベージコレクションは高価になる傾向があり、実行頻度が高すぎるとアプリのパフォーマンスに影響を与える可能性があります。
  3. CFCをどのようにインスタンス化していますか?クエリのすべての要求でCFCをインスタンス化する場合、時間の経過とともにRAMの問題が発生し、ガベージコレクションが追いつかないほどCFCがRAMにロードされるのが速すぎるため、メモリリークが遅くなります。あなたの最善の策は、これをシングルトンにすることです。(つまり、アプリケーションスコープに設定します)。
  4. 変数のvar-scopingは、変数の使用が停止しても(私が理解している限りでは)自動的にメモリを解放しないことに注意してください。メモリはまだ予約されていますが、(おそらく?)より速くクリーンアップされるように、短命の世代の一部として何らかの形でフラグが立てられている可能性があります。しかし、これは何も保証するものではありません。
  5. アクティブなスレッドを調べている場合は、リクエストが終了するまでクエリがクリアされない可能性もあります。必ずしも関数呼び出しが終了する必要はありません。関数呼び出しが完了するとすぐにクエリが終了することを期待するのは、やる気を起こさせるようです。
  6. ColdFusionクエリは、値ではなく参照によって渡されます。どういうわけかduplicate()または同様の関数を使用してクエリを明示的にコピーしない限り、メモリ内にクエリの2つのコピーを取得することは不可能です。

クエリは、cfreturnステートメントからクエリへのポインタを返す可能性があります。そのクエリは、それを参照するすべてのプロセスが完了するまでクリーンアップされません。したがって、クエリを他のプロセスに渡す場合、そのクエリをメモリからクリーンアップすることはできません。たとえば、そのクエリをセッション変数に設定すると、ガベージコレクションを強制しようとする頻度に関係なく、そのセッション変数がなくなるまでそのポインタはどこにも移動しません。

考慮すべき点がいくつかあります。

于 2010-03-02T19:20:30.163 に答える
0

大規模なデータ挿入の処理でも同様の問題が発生しました。各行には、複数のCFCを含む大規模な処理が必要です。<cfquery>によって作成されたJDBCResultSet、Statement、およびConnection参照は、要求が終了するまで保持されているようです。これは、クエリ変数をnullにしてもメモリ使用量に影響がないことを意味します。これを回避する方法は、100行を処理するためにCFC関数へのゲートウェイ呼び出しを行い、次にその関数がすべての行が処理されるまで次の100行などに対して別のゲートウェイ呼び出しを行うことでした。個々のゲートウェイ呼び出しは実際に終了するため、すべてのハンドルが解放され、そのメモリが回復されます。

于 2010-03-09T20:38:47.580 に答える