7

可能な重複:

C ++でプロセスのWorkingSetを強制的に1GBにする方法はありますか?

ページフォルトを回避するために、.NETプロセスのWorkingSetを1GBに増やしておきます。

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

更新

残念ながら、電話をかけてもSetProcessWorkingSetSizeExつまり、ガベージコレクションは、MinWorkingSetをバイパスして、とにかく作業セットを削除します(下の図の "Automatic GC.Collect()"を参照)。

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

これが素晴らしい理由は、ページフォルトが発生するたびにスレッドが250usの間ブロックされ、アプリケーションのパフォーマンスが著しく低下するためです。

enter image description here

更新

からの引用:「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 ++で書かれています(下記の私の答えを参照)。


  • そのメモリを占有するバッファを作成することができます。その後、必要に応じてバッファを埋めることができます。 - LMS
  • < a href ="を呼び出すことで、作業セットにしたいものをWindowsに伝えることができます。msdn.microsoft.com/ja-jp/library/windows/desktop/…">SetProcessWorkingSetSize< / a> < a href ="を介してpinvoke.net/default.aspx/…> - Gabe
  • @Yahia:GravitasがSE_INC_BASE_PRIORITY_NAMEを有効にして自分のプロセスを実行していないというだけではなかったと確信していますか。 - Gabe
  • GCからも電話をかけることは十分可能です。SetProcessWorkingSizeExワーキングセットを減らすために。 - Gabe
  • @OP:この質問とコメントの中のステートメントに注意してください。それらの多くは信頼されるべきではありません。仮想メモリがWindows上でどのように機能するかについて、私は多くの誤解を見つけることができます。 - usr

5 답변


4

あなたが欲しいものを達成するために、あなたは/ 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ラッパーです。ここに


  • これを掲載する予定でしたが、XP以降ではサポートされていません。 - Gabe
  • @Gabe Windows Server 2008 R2を使用しているので、XPをサポートする必要はありません。 - Contango
  • @Yahia特権の使い方を示すいくつかの良いコードがあります。processprivileges.codeplex.com。今週末にコードを試してみます。 - Contango
  • @Yahia私はあなたが正しいと思います。でのコードgate.upm.ro/os/Laborator/Utilitare_sistem_Windows/testlimit.cEnablePrivilege(SE_INC_BASE_PRIORITY_NAME)を呼び出す必要があることを示します。 SetWorkingSetSizeExを呼び出す前に。 C#ではなくC言語ですが、概念を実証していると思います。 - Contango

3

あなたの問題があなたのプロセスがそのWSがメモリ不足の状況であまりにも積極的にトリミングされていることであるならば、あなたはそれを世話することによって世話をすることができるSetProcessWorkingSetSizeまたは単に設定Process.CurrentProcess.MinWorkingSet

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

アドレス空間の問題を解決するには、すでに割り当てたオブジェクトを再利用する必要があります。あなたの問題がラージオブジェクトヒープに関するものであれば、それはおそらくコレクションによるものです。たとえば、新しい配列/リスト/辞書を作成するのではなく、そのClearメソッドとそれを再利用します。あなたの問題が文字列であるなら、あなたは使うことをやめることができるかもしれませんStringBuilderLOHから抜け出すためにs。

特定の種類のオブジェクトをたくさん作成している場合は、それらを集めてリサイクルすることを検討してください。私はそのようなことをしたことは一度もありませんが、それを実装するのであれば、パブリックコンストラクタを持たずにオブジェクトをプールから取り出してイニシャライザを呼び出す静的ファクトリメソッドでオブジェクトを作成します。それをプールに戻し、その中の参照をすべて無効にします。ニーズに応じて、プールはConcurrentBag<WeakReference<T>>


  • 残念ながら、GC.Collect()が実行されると、ワーキングセットを小さなものにリセットします。 50MBワーキングセットを恒久的に1GBに設定する方法はありますか? - Contango
  • @Gravitasこれは非常に興味深い質問です、あなたがこれを解決するかどうか私に知らせてください - l--''''''---------''''''''''''
  • あなたが呼び出す必要があることを回避するために@GravitasSetWorkingSetSizeEx(詳細は私の答えを見てください)... - Yahia
  • @Yahia:GravitasがSE_INC_BASE_PRIORITY_NAMEを有効にして自分のプロセスを実行していないというだけではなかったと確信していますか。 - Gabe
  • @Yahia SetProcessWorkingSizeExをQUOTA_LIMITS_HARDWS_MIN_ENABLEと共に使用してみましたが、GC.Collect()が呼び出されると、とにかく作業セットをトリミングします。 - Contango

2

プロセスをジョブオブジェクトと設定に割り当てるJOB_OBJECT_LIMIT_WORKINGSETそしてMinimumWorkingSetSizeうまくいくかもしれません。


  • すばらしいコメント、月曜日に試してみます。 - Contango

2

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

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

つまり、アプリケーションはメモリを大量に消費する可能性がありますが、実行速度は速くなります。言い換えれば、リアルタイム性能を向上させるためにメモリ使用量を犠牲にしています。


1

私はここで誤解があると思います:未使用のメモリを解放するGCは良い。 WSメトリックでより高い数値を表示するためだけに使用しても意味がありません。欲しいですWSの未使用メモリ。間違った測定基準に最適化しています。

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

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

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

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

では、GCの実行時にWSが縮小するのはなぜでしょうか。 GCだから削除多少のメモリ。何らかのWS制限を設定しても、メモリの削除を防ぐことはできません。

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


  • また、OPはソフトフォールトを無視するだけでよいと考えましたが、それから彼が「ページフォールトが発生するたびに250usの間スレッドをブロックする」と投稿したのを見ました。質問は「GC後250usの遅延をどうやって解消するか」でしたか。 - Gabe
  • これは別の質問です。この250usの遅延方法がどのように測定され、それがどのようにソフトフォールトに起因しているのかを知りたいと思います。ソフトフォールトパフォーマンスのヒットがGCパフォーマンスのヒットよりも大きいとは想像できません。 - usr
  • @usr Microsoft Studio 2012で利用可能なMicrosoft Concurrency Visualizerを使用して250usの遅延を測定しました。ソフトページフォルトが発生し、システム内の他のスレッドの実行がブロックされていることがわかりました。 - Contango

リンクされた質問


関連する質問

最近の質問