2

私の巨大な 32 ビット Web サービス LLBLGen ベースのデータ アクセス アプリケーションは、専用の 64 ビット マシンで単独で実行されています。プロセスが割り当てられたスペースのほとんどすべて (最大 1.5GB) を解放すると、その物理メモリの消費量は約 2GB まで着実に増加し、その時点から再び増加し続けます。ページ入力値やその他のページ ファイル使用パラメータに目に見える増加は見られないため、ページ ファイルにスワップ アウトされるのではなく、メモリが解放されたように見えます。これはどのようなプロファイルですか?プロセスが可能なすべてのメモリを取得することを実際に妨げるものは何もありませんが、メモリ解放の周りに容認できない http 内部エラーがあります - おそらくクリーンアップは有用な作業をブロックします。クリーンアップを邪魔にならないようにするための良い戦略は何でしょうか。

4

8 に答える 8

2

メモリ リークが発生しているようです。プロセスは、メモリ不足の状態でクラッシュし、サーバーによって自動的に再起動されるまでメモリ リークを続けます。

1.5GB は、32 ビット プロセスがアドレス空間を使い果たす前に割り当てることができるメモリの最大量です。

探すべきもの:

  • 独自のキャッシングを行っていますか? アイテムはいつキャッシュから削除されますか?
  • 時々コレクションにデータが追加され、決して削除されない場所はありますか?
  • IDisposable を実装するすべてのオブジェクトで Dispose を呼び出しますか?
  • 非マネージ コードにアクセスしますか (COM オブジェクトまたは DllImport を使用)、または非マネージ メモリを割り当てますか (たとえば、Marshal クラスを使用します)。そこに割り当てられたものはガベージ コレクターによって解放されることはありません。自分で解放する必要があります。
  • サードパーティのライブラリまたはサードパーティのコードを使用していますか? リストにある問題もある可能性があります。
于 2008-11-10T16:01:27.067 に答える
1

私はedgの答えの最初の部分に同意しますが、彼が言うところ:

「オブジェクトが死んでいるときにオブジェクトをnullに設定することで、GCがそれらのオブジェクトによって消費されるメモリを再利用するように促すことができ、これによりメモリの消費量の増加が制限されます。」

間違っています。オブジェクトが範囲外になった後、GC は最終的にオブジェクトを収集するため、オブジェクトを null に設定する必要はありません。

これについては、SO: Setting Objects to Null/Nothing after use in .NETに関するこの回答で説明されています。

于 2008-11-10T15:01:00.683 に答える
1

さまざまな使い捨てオブジェクト(特定のDB関連)を処分していない可能性はありますか。これにより、GC が実行されてファイナライザーが呼び出されるまで、大量の管理されていないリソースが拘束される可能性があります。

プロセスに対して perfmon を実行し、ハンドルなどの重要なリソースが着実に増加しているかどうか、または DB プロバイダーがパフォーマンス カウンターを公開してから接続または開いている結果セットを公開しているかどうかを確認する価値があります。

于 2008-11-10T14:59:53.323 に答える
0

アレイリストを使用しないでください(ガベージコレクトはそれらを使用しません)、代わりに汎用リストを使用してください

その他の一般的なエラーは、web.config Debug = trueにあることです。これは大量のメモリを消費するため、オプションを「false」に変更してください。

他に行うことは、CLRProfilerを使用して問題を追跡することです。

幸運、ペドロ

于 2008-11-10T15:14:25.320 に答える
0

私の最初の推測はメモリリークでしょう。私の2番目の推測は、これは正常な動作であるということです。メモリにかなりの負荷がかかるまで、GCは起動されません。確実にする唯一の方法は、プロファイラーとPerfMonなどを組み合わせて使用​​することです。いくつかのサイト:

さらに、(すでに述べたように)デバッグモードで実行されていないことを確認します。

HTTPエラーに関しては、サーバーGCモードで実行していると仮定すると、要求をブロックしないようにできる限りのことを実行しようとします。これらのHTTPエラーが何であるかを知ることは興味深いでしょう-それは私が過去に見たものからの通常の振る舞いではなく、あなたの問題の根本のいくつかを指し示すかもしれません。

于 2008-11-10T16:55:30.717 に答える
0

ガベージ コレクターは、オブジェクトを解放するときにメモリを自動的に解放しません。将来の malloc の費用を最小限に抑えるために、そのメモリを保持します。

メモリ不足の状態がトリガーされると、そのメモリが OS に戻され、タスク マネージャーを調べると、より多くの使用可能なメモリが表示されます。これは通常、2GB マーク、または関連するスイッチを使用する場合は 3GB について発生します。

<contentious>

オブジェクトが死んでいるときにオブジェクトを null に設定することで、GC がそれらのオブジェクトによって消費されるメモリを再利用するように促すことができ、これによりメモリの消費量の増加が制限されます。

しかし、どのオブジェクトを null に設定する必要がありますか? 大きなオブジェクト、大きなコレクション、頻繁に作成されるオブジェクト。

</contentious>

EDIT : オブジェクトを null に設定する価値を支持する証拠があります。詳しくはこちらをご覧ください。もちろん、オブジェクトを null に設定する必要はありません。重要なのは、メモリ管理に何らかの形で役立つということです。

編集:意見を続けるのではなく、そのようなものが存在する場合は、最近のベンチマークが必要です。

于 2008-11-10T14:39:33.050 に答える
0

プロジェクトのデバッグ ビルドを作成していないことを確認してください。デバッグビルドがある場合、イベントの定義を含むオブジェクトをインスタンス化すると、イベントを発生させなくても、メモリの小さな断片のみを無期限に保持する機能* があります。時間の経過とともに、これらの小さなメモリがメモリ プールを消費し、最終的に Web プロセスが再起動され、再び開始されます。

*.Net 2 (.Net 1.1 には存在しない) の初期から存在していたため、これを機能 (バグではなく) と呼んでおり、修正するパッチはありません。メモリ リークは、デバッグ時に必要な何らかの機能が原因である必要があります。

于 2008-11-10T16:22:57.303 に答える
0

同様の状況が発生していたため、すべてのデータベース接続を変更して、try/catch/finally アプローチを使用しました。Try は、コードを実行し、エラーを収集してキャッチし、最後にすべての変数とデータベース接続を閉じるために使用されました。

internal BECollection<ReportEntity> GetSomeReport()
    {
        Database db = DatabaseFactory.CreateDatabase();
        BECollection<ReportEntity> _ind = new BECollection<ReportEntity>();
        System.Data.Common.DbCommand dbc = db.GetStoredProcCommand("storedprocedure");

        try
        {
            SqlDataReader reader = (SqlDataReader)db.ExecuteReader(dbc);
            while (reader.Read())
            {
                //populate entity
            }
        }
        catch (Exception ex)
        {
            Logging.LogMe(ex.Message.ToString(), "Error on SomeLayer/SomeReport", 1, 1);
            return null;
        }
        finally
        {
            dbc.Connection.Close();
            _ind = null;
        }
        return _ind;
    }
于 2008-11-10T16:25:55.067 に答える