読者です 読者をやめる 読者になる 読者になる

ソフトページフォールト

"Working Set" から外されたメモリページは,直ちにディスク上に退避されるわけではありません*1.ページが「変更済みページリスト」或いは「スタンバイページリスト」に留まっている間に再度メモリアクセスが発生した場合は,ページはページフォールトを経てすぐにワーキングセットに復帰します.このようなディスクアクセスを伴わないページフォールトは「ソフトページフォールト」と呼ばれています.
"Working Set" 上のメモリアクセスに比べれば,ソフトページフォールトを伴うメモリアクセスは当然オーバーヘッドを伴います.実際これは簡単なコードで計測可能です.x86 CPU 上の Windows XP はデフォルトで 4KB ページを使用するので,ページフォールトの影響を見るだけであれば 4KB ごとにアクセスすれば十分です.256MB のバッファであれば 256MB / 4KB = 65536 回の DWORD 書き込みで検出可能なはずです.手元の環境 *2 では次のようになりました.

以下にサンプルコードを載せておきました.プロセスワーキングセット解放のために,SetProcessWorkingSetSize API を使用しています.

int main()
{
    const DWORD numByte = 1024 * 1024 * 256;
    DWORD* buf = (DWORD*) VirtualAlloc ( NULL, numByte, MEM_COMMIT, PAGE_READWRITE );

    const DWORD numDWord = numByte / sizeof(DWORD);
    const DWORD skip = 4096 / sizeof(DWORD);

    // 最初のメモリアクセスは,Demand-Zero Page Fault を発生させる
    for( int i = 0; i < numDWord; i+=skip )
    {
        buf[i] = i;
    }

    DWORD tmp = 0;

    // ワーキングセット上のメモリアクセスは Page Fault を発生させない
    for( int i = 0; i < numDWord; i+=skip )
    {
        tmp += buf[i];
    }

    // ワーキングセットからバッファを追い出す
    BOOL ret = SetProcessWorkingSetSize( GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1 );
    
    Sleep( 1000*1 );

    // 変更済みページリストへのアクセスは Soft Page Fault を発生させる
    for( int i = 0; i < numDWord; i+=skip )
    {
        tmp += buf[i];
    }

    return tmp;
}

*1:『インサイドMicrosoft Windows (上)』 7.11.1 ページリストと状態遷移

*2:Windows XP SP2,Intel XEON(Prestonia)@2GHz×2,DDR DPC2100 ECC 1536MB