ページフォルトを回避するために、.NETプロセスのWorkingSetを1GBに増やしておきます。
.NETでこれを行う方法はありますか?
更新
残念ながら、電話をかけてもSetProcessWorkingSetSizeExつまり、ガベージコレクションは、MinWorkingSetをバイパスして、とにかく作業セットを削除します(下の図の "Automatic GC.Collect()"を参照)。
下の図では、新しいメモリをプロセスに割り当てるときに発生するページフォルトの急上昇(赤い線)を回避するために、プロセスWorkingSet(緑色の線)を1GBにロックする方法はありますか。
これが素晴らしい理由は、ページフォルトが発生するたびにスレッドが250usの間ブロックされ、アプリケーションのパフォーマンスが著しく低下するためです。
更新
からの引用:「C / C ++によるWindows、第5版、Jeffrey Richter(Wintellect)」
個々のプロセスによるSetProcessWorkingSetSizeの呼び出しは無視されます プロセスがワーキングセットを空にしようとしているのでない限り。設定する この制限については、JOB_OBJECT_LIMIT_WORKINGSETフラグを LimitFlagsメンバー
この本では、WorkingSetを設定する唯一の方法は、プロセスをJob Objectに割り当て、JOB_OBJECT_LIMIT_WORKINGSETとMinimumWorkingSetSizeを設定することです。
更新
SetProcessWorkingSetSizeExは、ソフトページフォルトとはまったく関係ありません。現在のWorkingSet内のメモリがハードドライブにページアウトされないようにするため、ハードページフォルトのみを参照します。
更新
WorkingSetを増やす唯一の方法は、非常に特殊な方法で.NETを実行することです。CLRホストC ++で書かれています(下記の私の答えを参照)。
あなたが欲しいものを達成するために、あなたは/ pinvokeを呼ぶ必要がありますSetWorkingSetSizeEx最小1 GB(2番目のパラメータ)QUOTA_LIMITS_HARDWS_MIN_ENABLE
ワーキングセットのサイズが最小値を下回らないようにするための4番目のパラメータとして、システムの「メモリ不足」状態でも与えたものです。
システムの動作は、あなたが必要とするかもしれないOSのバージョンなどに応じて、呼び出し側の特権にも依存しますSE_INC_WORKING_SET_NAME
および/またはSE_INC_BASE_PRIORITY_NAME
!
「舞台裏で」これらのAPIを使用するもう1つの(より良い)オプションは、あなたが見つけることができる.NETラッパーです。ここに。
あなたの問題があなたのプロセスがそのWSがメモリ不足の状況であまりにも積極的にトリミングされていることであるならば、あなたはそれを世話することによって世話をすることができるSetProcessWorkingSetSize
または単に設定Process.CurrentProcess.MinWorkingSet
。
しかし、あなたが示したことは、あなたのワーキングセットがGCによって削減されつつあるということです。これは、本当に起こっていることはGCがあなたのWSを構成するページの割り当てを解除していることであることを私に告げています。この場合、ワーキングセットの問題ではなくアドレス空間の問題があります。それを防ぐためのシステムコールはありません。理想的には、GCにメモリをOSに返さないように指示できますが、.NETにはそのような機能はありません。
アドレス空間の問題を解決するには、すでに割り当てたオブジェクトを再利用する必要があります。あなたの問題がラージオブジェクトヒープに関するものであれば、それはおそらくコレクションによるものです。たとえば、新しい配列/リスト/辞書を作成するのではなく、そのClear
メソッドとそれを再利用します。あなたの問題が文字列であるなら、あなたは使うことをやめることができるかもしれませんStringBuilder
LOHから抜け出すためにs。
特定の種類のオブジェクトをたくさん作成している場合は、それらを集めてリサイクルすることを検討してください。私はそのようなことをしたことは一度もありませんが、それを実装するのであれば、パブリックコンストラクタを持たずにオブジェクトをプールから取り出してイニシャライザを呼び出す静的ファクトリメソッドでオブジェクトを作成します。それをプールに戻し、その中の参照をすべて無効にします。ニーズに応じて、プールはConcurrentBag<WeakReference<T>>
。
SetWorkingSetSizeEx
(詳細は私の答えを見てください)... - Yahia
プロセスをジョブオブジェクトと設定に割り当てるJOB_OBJECT_LIMIT_WORKINGSET
そしてMinimumWorkingSetSize
うまくいくかもしれません。
ソフトページフォルトを減らすために.NETでプロセスのワーキングセットを増やすことができる唯一の方法は、カスタムで.NETアプリケーション全体を実行することでした。CLRホスト。これは自明ではない演習で、約800行のカスタム作成された、かなり密度の高いC ++コードが必要です。 C ++コードは、Win32メモリ管理メソッドへの.NET呼び出しをインターセプトし、.NETランタイムの動作を変更して、通常のように積極的にメモリを解放しないようにします。
これには、アプリケーションの起動時にすべてのソフトページフォルトが発生するという影響があります。そのため、通常のアプリケーション実行中には、.NETアプリケーションのソフトページフォルトの数はほとんどゼロになります。
つまり、アプリケーションはメモリを大量に消費する可能性がありますが、実行速度は速くなります。言い換えれば、リアルタイム性能を向上させるためにメモリ使用量を犠牲にしています。
私はここで誤解があると思います:未使用のメモリを解放するGCは良い。 WSメトリックでより高い数値を表示するためだけに使用しても意味がありません。欲しいですWSの未使用メモリ。間違った測定基準に最適化しています。
ソフトフォールトとハードフォールトがあるため、ページフォールトの数はそれほど重要ではありません。ハードフォルトがディスクから読み取りました。ソフトフォールトは、ほとんどの場合意味がありません。それらはOSの実装の詳細です。たとえば、新しく割り当てられたページごとに、ソフトフォルトが発生します。
これはあなたの赤いグラフがハードフォルトを示していないといういくつかの証拠です:最後にそれは約500 /秒を示しています。お使いのディスクは500 IOPを配信できないため、ハードフォールトにはなりません。
あなたはおそらくハードフォルトのみを測定(そして削減)したいと思うでしょう。ハードフォールトのみがパフォーマンスに意味のある方法で影響を与えます。
また、WS制限を設定しても、GCの動作には影響しません。 GCはオペレーティングシステムのコンポーネントではありません。ユーザーモードのライブラリです。 OSがワーキングセットとして使用することを決定したものとは関係ありません。そのため、WS制限を設定してもGCがメモリを解放しないようにすることはできません。
では、GCの実行時にWSが縮小するのはなぜでしょうか。 GCだから削除多少のメモリ。何らかのWS制限を設定しても、メモリの削除を防ぐことはできません。
コメントでは、ワーキングセットを縮小するために、GC自体が何らかのAPIを呼び出す可能性があることが示唆されました。それがなぜそうなるのか私は全く理由を全く見ることができません。なぜGCはページをプロセスから追い出すのでしょうか。覚えておいてください:WSと割り当てられたページは同じではありません(まったく!)。 GCが解放するメモリ。 WSを縮小させるわけではありません。どんな目的がありますか?
SetProcessWorkingSetSize
< / a> < a href ="を介してpinvoke.net/default.aspx/…> - GabeSetProcessWorkingSizeEx
ワーキングセットを減らすために。 - Gabe