6

C ++で次の呼び出しを使用すると、プロセスのWorkingSetが100MBを下回ることはありません。

ただし、この呼び出しを行っても、OSは作業セットを16MBに戻します。

WorkingSetを100MBに設定すると、ソフトページのページフォルトが解消され、アプリケーションの速度が劇的に向上します(下図を参照)。

何がおかしいのですか?

SIZE_T workingSetSizeMB = 100;
int errorCode = SetProcessWorkingSetSizeEx(
    GetCurrentProcess(),
    (workingSetSizeMB - 1) * 1024 * 1024), // dwMinimumWorkingSetSize
    workingSetSizeMB * 1024 * 1024,  // dwMaximumWorkingSetSize,
    QUOTA_LIMITS_HARDWS_MIN_ENABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE
  );
// errorCode returns 1, so the call worked.

(専門家向け) 実験方法

ワーキングセットを100MB以上にするために100MBのデータを割り当てるテストC ++プロジェクトを作成し(Process Explorer内で)、そのメモリの割り当てを解除しました。しかし、OSがワーキングセットを16MBに戻してみたところ、そのメモリの割り当てが解除されました。ご希望の場合は、私が使用したテストC ++プロジェクトを提供できます。

WindowsがSetProcessWorkingSetSizeEx()への呼び出しを提供していますが、それが機能していないように見える場合はなぜですか?私は何か悪いことをしているに違いない。

下の図は、緑色の線(ワーキングセット)が50MBから30MBに減少したときのソフトページフォルト(赤いスパイク)の数の劇的な増加を示しています。

Example showing the increase in soft page faults when the WorkingSet is reduced too low

更新

結局、パフォーマンスにそれほど影響を与えなかったので、問題を無視しました。

さらに重要なことに、SetProcessWorkingSetSizeExはではない現在のWorkingSetを制御します。ではないソフトページフォルトに何らかの形で関係しています。現在行われているワーキングセットがハードドライブにページアウトされないようにすることで、ハードページフォルトを防止します。

言い換えれば、ソフトページフォルトを減らしたい場合、SetProcessWorkingSetSizeExはハードページフォルトを指すのでまったく効果がありません。

"Windows via C / C ++"(Richter)には、Windowsがメモリをどのように扱うかについての素晴らしい記事があります。


  • OSが割り当てたページ数よりも多くのページをメモリに保持するとどう思いますか。 - James McNellis
  • なぜあなたはメモリを解放しているのですか? - Mat
  • ガベージコレクタがパフォーマンスに大きな影響を与えている場合は、割り当てポリシーを確認してください。 - Mat
  • オブジェクトの再利用(オブジェクトのプール)は(時に)可能です。 GCがないからといって、オブジェクトをいつ割り当てて放棄するかを制御できないわけではありません。 - Mat
  • @ Gravitas:あなたはマイルでポイントを逃しています。ワーキングセットには、現在RAMにあるメモリブロックが割り当てられます。直接制御できるものではありません。はい、作業セットのサイズを特定の値にするためにブロックを割り当てることはできますが、それが解放されるとすぐにブロックは削除され、使用できなくなるか、または作業セットの一部になります。それは魔法のようにOSページを他のものに戻したり、あなたのプロセスのためにそれを保存したりすることはありません。メモリのスワップアウトを止めるには、解放したり、使い続けたりしないでください。 - Deanna

1 답변


4

ページフォルトは安価であり、予想されるものです。リアルタイムアプリケーション、ハイエンドゲーム、高密度処理、およびBlu-ray再生はすべて、ページフォルトが発生してもフルスピードでうまく動作します。ページフォルトがあなたのアプリケーションが遅い理由ではありません。

アプリケーションが遅い理由を調べるには、アプリケーションのアプリケーションプロファイリングをいくつか行う必要があります。

具体的にあなたの質問に答えるために - あなたがちょうどGC.Collect()を持っていたときに起こっているページフォルトはページインフォルトではなく、それらはGCがちょうど割り当てたという事実によって引き起こされる要求ゼロページフォルトですオブジェクトを移動するための、要求がゼロになったページの新しい巨大なブロック。デマンドゼロページはページファイルから処理されず、ディスクコストもかかりませんが、それでもページフォルトのため、グラフに表示されます。

一般的な規則として、Windowsはあなたよりもあなたのシステムリソースを管理することにおいて優れています、そしてそれはデフォルトが通常のプログラムの平均的な場合のために高度に調整されています。あなたの例から、あなたがガベージコレクタを使っていることは明らかです。それゆえ、ワーキングセットや仮想メモリなどを扱うタスクはすでにGCの実装に移されました。 SetProcessWorkingSetSizeがGCのパフォーマンスを向上させるための優れたAPI呼び出しであれば、GCの実装がそれを行います。

あなたへの私のアドバイスはあなたのアプリをプロファイルすることです。マネージドアプリケーションの動作が遅くなる主な原因はマネージドコードの書き方が悪いことです。GCが遅くなるのではありません。アルゴリズムのbig-Oパフォーマンスを向上させ、FutureやBackgroundWorkerのようなものを使用して高価な作業を軽減し、ネットワークへの同期要求を避けようとします。プロフィールそれ。


  • 私たちは、Microsoft Concurrency Visualizerを使用して、アプリ内で起こっていることについての洞察を得ました。結局、パフォーマンスの低下は心配するのに十分ではありませんでした。 - Contango

リンクされた質問


関連する質問

最近の質問