6

次の非常に奇妙な状況と問題があります。

  • ダイアグラム編集用の .NET 4.0 アプリケーション (WPF)。

  • 私の PC では正常に動作します: 8GB RAM、3.0GHz、i7 クアッドコア。

  • オブジェクト (主にダイアグラム ノードとコネクタ、およびすべての元に戻す/やり直し情報) の作成中に、タスク マネージャーは、予想どおり、メモリ使用量が「ジャンプ」(上下) することを示します。

  • これらのメモリ使用量の「ジャンプ」は、ユーザーの操作が終了した後も実行され続けます。多分これはGCのクリーニング/再編成メモリですか?

  • 何が起こっているのかを確認するために、Ants mem プロファイラーを使用しましたが、ユーザーの操作後にこれらの「ジャンプ」が発生するのをある程度防ぎます。

問題: ベータ テスターの一部の遅い/弱いラップトップ/ネットブック (速度が 2GHz 未満、RAM が 2GB 未満) で数秒または数分使用するとフリーズ/ハングします。メモリリークかと思ったけど…

EDIT 1: また、メモリ使用量が増加し、崩壊するまで増加する場合があります (遅いマシンでのみ)。

  • 512MB の RAM しか割り当てられていない Windows XP モード マシン (Win 7 の VM) では、ユーザーの操作後にメモリ使用量が "ジャンプ" することなく正常に動作します (GC クリーニングなし?!)。

編集 2: システムで他の負荷の高いプログラム (Visual Studio、Office、Web ページが開いているなど) が実行されている場合、問題はさらに悪化します。メモリ使用量が宇宙へのロケットのように上昇している間は、ダイアグラムの最初のシンボルでさえ作成できません (数秒で数百 MB が消費されます)。似たような経験をした人はいますか?彼らはどのような戦略でしたか?

したがって、エラーを再現できず、これらの奇妙な動作 (mem jumps) しか表示されず、何が起こっているのかを表示するはずのツールが問題を隠しているため (「オブザーバーのパラドックス」のように)、私は本当に大きな問題を抱えています。

何が起こっているのか、それを解決する方法についてのアイデアはありますか?

編集 3: Ants メモリ プロファイラーのこのスクリーンショットは、管理されていないリソースからの場合、RAM が (クレッシェンドで) 大量に消費されることを示しています。

ここに画像の説明を入力

しかし、これほど多くのメモリを高速に消費するのはなぜでしょうか??!!!

4

3 に答える 3

6

あなたが説明しているのは、.NET プログラムの完全に正常な動作であり、コードに問題があることを示すものではありません。

最大の問題は、TaskMgr.exe が、プロセスで何が起こっているかを伝えるのに適したプログラムではないということです。プロセスの「ワーキング セット」を表示します。この数値は、プロセスが使用するメモリの量とはほとんど関係がありません。

ワーキング セットは、プロセスが使用する RAM の量です。すべてのプロセスは、コードとデータに使用する2 ギガバイトの仮想メモリを取得します。512 MB の RAM しかない仮想 XP ボックスでも。ただし、これらのプロセスはすべて、動作する一定量の RAM しかありません。ギガバイトほどの低価格のマシンで。

明らかに複数のプロセスが実行されており、それぞれがギガバイトの仮想メモリを持ち、実際のメモリはわずか 1 ギガバイトです。これはオペレーティング システムによって提供され、Windows は RAM を仮想化します。つまり、2 ギガバイトの RAM を搭載したマシン上で各プロセスが独自に実行されているような錯覚を引き起こします。これは、ページングと呼ばれる機能によって行われます。プロセスがメモリの読み取りまたは書き込みを行う必要があるときはいつでも、オペレーティング システムは物理メモリを提供するために RAM のチャンクを取得します。

必然的に、別のプロセスから RAM を奪って、自分のプロセスで利用できるようにする必要があります。以前にその RAM のチャンクにあったものはすべて保持する必要があります。それがページング ファイルの機能です。ページ アウトされた RAM の内容を保存します。

明らかに、これは無料ではありません。ディスクはかなり遅く、ページングは​​高価な操作です。そのため、いくつかの大きなプログラムを実行するように頼むと、性能の低いマシンのパフォーマンスが低下します。これに対する実際の対策は TaskMgr.exe にも表示されますが、追加する必要があります。表示 + 列を選択し、「ページ フォールト デルタ」にチェックマークを付けます。プロセスの実行中にこの数を観察します。スパイクが見られると、プログラムの速度が大幅に低下し、表示されるメモリ使用量が急速に変化することが予想されます。

あなたの観察に対処する:

オブジェクトの作成...タスクマネージャーは、予想どおり、メモリ使用量が「ジャンプ」することを示しています

はい、RAM を使用しているため、ワーキング セットが増加します。

これらのメモリ使用量の「ジャンプ」は、ユーザーの操作が終了した後も実行され続けます

スラムダンクはありませんが、RAM を順番に使用し、他のプロセスの実行時間を増やして、他のプロセスの実行時間を増やします。ページ フォールト デルタ列を確認します。

私は Ants mem プロファイラーを使用しましたが、ユーザーの操作後にこれらの「ジャンプ」が発生するのをある程度防ぎます。

はい、メモリプロファイラーは、プログラムの実際のメモリ使用量、つまり仮想メモリの種類に焦点を当てています。彼らは主にワーキング セットを無視します。それについてできることは何もありません。また、他のプロセスが実行されているかどうかに実際に依存するため、数値は無意味です。

メモリ使用量が増えて崩壊するまで増える場合がある

これはガベージ コレクターの副作用である可能性がありますが、一般的ではありません。おそらく、Windows がワーキング セットをトリミングし、ページを削除して、消費しすぎないようにしているのを見ているだけでしょう。

512MB の RAM しか割り当てられていない Windows XP モード マシン (Win 7 の VM) では、正常に動作します。

これは、その WM に RAM を競合する大きなプログラムをインストールしていないことが原因である可能性があります。XP はメモリが非常に少ないマシンでもうまく動作するように設計されており、256 MB のマシンではスムーズに動作します。これは、Vista/Win7 にはまったく当てはまらず、最新のマシン ハードウェアを利用するように設計されています。Aero のような機能は目を楽しませてくれますが、非常に高価です。

システムに他の重いプログラムが実行されている場合、問題はさらに悪化します

はい、大量の RAM を必要とする他のプロセスと競合しています。

メモリ使用量がロケットのように上昇している間は、ダイアグラムの最初のシンボルでさえ作成できません

はい、ページが RAM にマップされ、ページング ファイルと ngen-ed .ni.dll ファイルからリロードされます。ワーキングセットを再び急速に増やします。また、ページ フォールト デルタ数のピークも見られます。

結論として、WPF プログラムは大量のメモリを消費し、適切に動作するには馬力が必要です。これを修正するのは簡単ではありません。リソース要件を下げるには、かなり抜本的な再設計が必要です。したがって、システム要件をボックスに記載するだけで、そうすることはまったく正常です。

于 2012-04-16T18:02:27.293 に答える
2

コードを見ずに何が起こっているのかを正確に知ることは困難ですが、いくつかの提案を以下に示します。

まず、ガベージ コレクターに関する情報です。知っておくべき最も重要なことは、GC は非決定論的であり、いつ実行されるかを知ることができないということです。GC.Collect() の呼び出しでさえ、コマンドではなく単なる提案です。Gen0 ヒープは、ローカル スコープのオブジェクト用であり、頻繁に収集されます。オブジェクトが Gen0 コレクションに残っている場合、そのオブジェクトは Gen1 ヒープに移動されます。しばらくすると、Gen1 ヒープが収集され、オブジェクトが収集に耐えた場合、収集頻度の低い Gen2 ヒープに移動されます。このため、Gen1 または Gen2 ヒープに多くのオブジェクトを割り当てている場合、メモリ グラフに鋸歯状のパターンが見られることがあります。

Process Explorerなどのツールを使用して、マネージド ヒープ (Gen0、Gen1、Gen2、および大きなオブジェクト ヒープ) のサイズを調べ、メモリが保持されている場所を見つけます。存続期間の短いオブジェクト (Gen1 ヒープ) が多数ある場合は、メモリを再割り当てする代わりに、メモリを再利用する方法を考えてください。これには、オブジェクト プールのようなものが適しています。

また、マネージド ヒープの合計サイズをアプリケーションのプライベート バイトの合計と比較してみてください。プライベート バイトには、アプリケーションによって割り当てられたマネージド メモリとアンマネージド メモリの両方が含まれます。マネージ ヒープのサイズとプライベート バイトのサイズに大きな違いがある場合は、アプリケーションが (グラフィック オブジェクト、ストリームなどを介して) 正しく破棄されていないアンマネージ オブジェクトを割り当てている可能性があります。IDisposable を実装しているが、Dispose() が呼び出されていないオブジェクトを探します。

別の問題として、ヒープの断片化が考えられます。アプリケーションが現在のヒープに収まらない大きなオブジェクトを割り当てている場合、OS からより多くのメモリを要求します。これを回避する解決策は、より小さなチャンクまたはメモリを割り当てるか、ランダムではなく順次ブロックに割り当てることです (配列と連結リストを考えてください)。ANTS メモリ プロファイラーのようなツールは、これが行われていることを通知できるはずです。

PerfView (または CLR プロファイラーの前身) の @ReedCopsey の推奨事項は優れたものであり、メモリがどのように割り当てられているかをよりよく理解できます。

于 2012-04-14T20:39:01.337 に答える