7

重複の可能性:
プロセスのWorkingSetをC ++で1GBにする方法はありますか?

ページフォールトを回避するために、事前に.NETプロセスのワーキングセットを1GBに増やしたいと思います。

.NETでこれを行う方法はありますか?

アップデート

残念ながら、SetProcessWorkingSetSizeExを呼び出しても、ガベージコレクションは、MinWorkingSetをバイパスしてワーキングセットをトリミングしているようです(下の図の「自動GC.Collect()」を参照)。

下の図では、プロセスに新しいメモリを割り当てるときに発生するページフォールト(赤い線)の急増を回避するために、プロセスのワーキングセット(緑の線)を1GBにロックする方法はありますか?

これがすばらしい理由は、ページフォールトが発生するたびに、250usのスレッドがブロックされ、アプリケーションのパフォーマンスに大きな影響を与えるためです。

ここに画像の説明を入力してください

アップデート

引用元:「Windowsvia C / C ++、第5版、Jeffrey Richter(Wintellect)」

プロセスがワーキングセットを空にしようとしているだけでない限り、個々のプロセスによるSetProcessWorkingSetSizeの呼び出しは無視されます。この制限を設定するには、LimitFlagsメンバーでJOB_OBJECT_LIMIT_WORKINGSETフラグを指定します。

この本は、WorkingSetを設定する唯一の方法は、プロセスをジョブオブジェクトに割り当て、JOB_OBJECT_LIMIT_WORKINGSETとMinimumWorkingSetSizeを設定することであることを示唆しています。

アップデート

SetProcessWorkingSetSizeExは、ソフトページフォールトとはまったく関係がありません。現在のワーキングセットのメモリがハードドライブにページアウトされるのを防ぐため、ハードページフォールトのみを参照します。

アップデート

ワーキングセットを増やす唯一の方法は、C ++で記述された非常に特殊なCLRホストを使用して.NETを実行することです(以下の私の回答を参照)。

4

5 に答える 5

4

必要なものを実現するには、最小で1 GB(2番目のパラメーター)および4番目のパラメーターとしてSetWorkingSetSizeExを呼び出し/ピンボークする必要があります。QUOTA_LIMITS_HARDWS_MIN_ENABLEこれにより、システムの「メモリ負荷が高い」状態でも、ワーキングセットのサイズが最小値を下回らないようになります。 。

システムの動作は、必要なOSのバージョンなどに応じて、呼び出し元の特権にも依存しSE_INC_WORKING_SET_NAMEますSE_INC_BASE_PRIORITY_NAME

これらのAPIを「舞台裏で」使用するもう1つの(より優れた)オプションは、ここにある.NETラッパーです。

于 2012-08-31T19:56:05.567 に答える
3

プロセスがメモリ不足の状況でWSを積極的にトリミングしすぎていることが問題である場合は、を呼び出すSetProcessWorkingSetSizeか、設定するだけで対処できますProcess.CurrentProcess.MinWorkingSet

ただし、これまでに示したのは、ワーキングセットがGCによって削減されていることです。これは、実際に起こっているのは、GCがWSを構成するページの割り当てを解除していることを示しています。この場合、ワーキングセットの問題ではなく、アドレススペースの問題があり、それを防ぐためにシステムコールをかけることはできません。理想的には、メモリをOSに戻さないようにGCに指示できますが、.NETにはそのような機能はありません。

アドレス空間の問題を解決するには、すでに割り当てたオブジェクトを再利用する必要があります。問題がラージオブジェクトヒープにある場合は、コレクションが原因である可能性があります。たとえば、新しい配列/リスト/ディクショナリを作成するのではなく、そのClearメソッドを呼び出して再利用します。StringBuilder問題が文字列である場合は、 sを使用してLOHを回避できる可能性があります。

たくさん作成する特定の種類のオブジェクトがある場合は、それらのプールを作成してリサイクルすることを検討してください。私はそのようなことをしたことはありませんが、それを実装する場合は、パブリックコンストラクターを使用する代わりに、オブジェクトをプールから引き出して初期化子を呼び出す静的ファクトリメソッドを使用してオブジェクトを作成し、それにファイナライザーを配置します。それをプールに戻し、その中の参照をすべて無効にします。必要に応じて、プールはになりますConcurrentBag<WeakReference<T>>

于 2012-08-31T19:45:38.570 に答える
2

JOB_OBJECT_LIMIT_WORKINGSETプロセスをジョブオブジェクトに割り当てて設定すると、MinimumWorkingSetSizeうまくいくと思います。

于 2012-09-01T07:58:09.590 に答える
2

ソフトページフォールトを減らすために、.NETでプロセスのワーキングセットを増やすことができる唯一の方法は、カスタムCLRホストで.NETアプリケーション全体を実行することでした。これは簡単なことではなく、約800行のカスタム作成されたかなり高密度のC++コードが必要です。C ++コードは、Win32メモリ管理メソッドへの.NET呼び出しをインターセプトし、.NETランタイムの動作を変更して、通常ほど積極的にメモリを解放しないようにします。

これには、アプリケーションの起動時にすべてのソフトページフォールトが発生する効果があるため、通常のアプリケーション実行中に、.NETアプリのソフトページフォールトの数はほぼゼロになります。

これは、アプリケーションがメモリを大量に消費している可能性があることを意味しますが、実行速度は速くなります。つまり、リアルタイムのパフォーマンスを向上させるために、メモリ使用量を犠牲にしています。

于 2012-09-21T11:46:47.153 に答える
1

ここには誤解があると思います。GCが未使用のメモリを解放するのは良いことです。WSメトリックでより高い数値を確認するためだけに、それを維持することは役に立ちません...WS未使用のメモリは必要ありません。間違ったメトリックを最適化しています。

ソフトフォールトとハードフォールトがあるため、ページフォールトの数はそれほど意味がありません。ディスクから読み取られたハード障害。ソフトフォールトはほとんどの場合何の意味もありません。これらは、OSの実装の詳細です。たとえば、新しく割り当てられたページごとに、ソフトフォールトが発生します。

赤いグラフがハードフォールトを示していないことを示すいくつかの証拠があります。最後に、約500/秒を示しています。ディスクは500IOPを配信できないため、ハードフォールトになることはありません。

おそらく、ハード障害のみを測定(および削減)したいと思うでしょう。ハードフォールトのみが、意味のある方法でパフォーマンスに影響を与えます。

また、WS制限の設定は、GCの動作には影響しません。GCはオペレーティングシステムのコンポーネントではありません。Isはユーザーモードライブラリです。これは、OSがワーキングセットとして使用することを決定したものとは何の関係もありません。そのため、WS制限を設定してGCにメモリを解放させないようにすることはできません。

では、GCの実行時にWSが縮小するのはなぜですか?GCが一部のメモリを削除するためです。WS制限を設定しても、メモリの削除を防ぐことはできません。

コメントでは、GC自体がワーキングセットを縮小するために何らかのAPIを呼び出す可能性があることが示唆されました。それがなぜそうなるのか、私にはまったく理由がわかりません。GCがページを強制的にプロセスから外すのはなぜですか?注意:WSと割り当てられたページは同じではありません(まったく同じではありません!)。GCがメモリを解放する可能性があります。WSを強制的に縮小することはありません。それにはどのような目的がありますか?

于 2012-09-02T13:26:46.243 に答える