ソフトページフォールト
"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; }