6

C++ で次の呼び出しを使用すると、プロセスの WorkingSet が 100MB を下回らないことが予想されます。

ただし、この呼び出しを行っても、OS はワーキング セットを 16 MB に戻します。

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 のデータを割り当てて WorkingSet を 100MB (Process Explorer 内で表示) を超えるテスト C++ プロジェクトを作成し、そのメモリの割り当てを解除しました。ただし、そのメモリの割り当てを解除するとすぐに、OS は WorkingSet を 16 MB に戻しました。ご希望であれば、私が使用したテスト C++ プロジェクトを提供できます。

Windows が SetProcessWorkingSetSizeEx() の呼び出しを提供しているのに、機能していないように見えるのはなぜですか? 私は何か間違ったことをしているに違いない。

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

WorkingSet の値を下げすぎた場合のソフト ページ フォールトの増加を示す例

アップデート

結局、パフォーマンスにそれほど影響を与えなかったため、問題を無視することになりました。

さらに重要なことに、SetProcessWorkingSetSizeEx は現在の WorkingSet を制御せ、ソフト ページ フォールトとはまったく関係がありません。現在の WorkingSet がハード ドライブにページ アウトされるのを防ぐことで、ハード ページ フォールトを防ぐだけです。

つまり、ソフト ページ フォールトを減らしたい場合、SetProcessWorkingSetSizeEx はハード ページ フォールトを参照するため、まったく効果がありません。

「Windows via C/C++」(Richter) には、Windows がメモリをどのように扱うかについての優れた記事があります。

4

1 に答える 1

4

ページ フォールトは安価であり、予期されることです。リアルタイム アプリケーション、ハイエンド ゲーム、高負荷の処理、および BluRay 再生はすべて、ページ フォールトを使用してフル スピードで快適に動作します。ページ フォールトは、アプリケーションが遅い理由ではありません。

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

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

原則として、Windows はユーザーよりもシステム リソースの管理に優れており、その既定値は通常のプログラムの平均的なケースに合わせて高度に調整されています。あなたの例から、ガベージ コレクターを使用していることは明らかです。そのため、ワーキング セットや仮想メモリなどを処理するタスクを既に GC 実装にオフロードしています。SetProcessWorkingSetSize が GC のパフォーマンスを改善するための適切な API 呼び出しである場合、GC 実装がそれを行います。

あなたへの私のアドバイスは、あなたのアプリをプロファイリングすることです。マネージド アプリケーションの速度低下の主な原因は、不適切なマネージド コードを記述していることです。GC が速度を低下させているわけではありません。アルゴリズムの大きなパフォーマンスを改善し、Future や BackgroundWorker などを使用してコストのかかる作業をオフロードし、ネットワークへの同期リクエストを行わないようにします。ただし、何よりも、アプリを高速化するための鍵はアプリをプロファイリングすることです。

于 2012-09-06T11:56:46.470 に答える