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

メモリマップドファイルとワーキングセット

メモリマップドファイルも "Working Set" を消費します.試しに 256MB のファイルをメモリ空間にマッピングしてみましょう.
まずはファイルの作成からです.@IT で紹介されている『巨大なサイズのファイルを簡単に作る方法』で 256MB のファイルを作成しました.

fsutil file createnew image.bin 268435456

では,このファイルにデータを書き込みながら仮想メモリの使用状況を見ていきましょう.

int main()
{
    Sleep( 1000 * 3 );

    const DWORD numByte = 1024 * 1024 * 256;

    HANDLE file = CreateFileW( L"image.bin", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
    HANDLE mmap = CreateFileMappingW( file, NULL, PAGE_READWRITE | SEC_COMMIT, 0, numByte, NULL );
    DWORD* buf = (DWORD*) MapViewOfFile( mmap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, numByte );

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

    // Page Fault を発生させる
    for( int i = 0; i < numDWord; i+=skip )
    {
        buf[i] = i;
    }

    UnmapViewOfFile( buf );
    CloseHandle( mmap );
    CloseHandle( file );

    return 0;
}


まずこれはプロセス起動直後のものです."vmtest.exe" というのが今回用意したテストプログラムですね.


次に MapViewOfFile 直後のものです."Virtual Size" が増加して,image.bin がメモリマップされたことが下部ペインに見て取れます.一方,"Private Bytes" はほとんど増加していないことに注意してください.


さらに 128MB 程度アクセスした時点でのメモリ使用量です.デマンドページングによって "Working Set" が必要量割り当てられているのが分かります.


最後の 256MB 全てアクセス完了した時点でのメモリ使用量です.OS によってファイルアクセスのためのバッファとして 256MB 程度の物理メモリが割り当てられたということになります.

あまりにも巨大なファイルをメモリ空間にマッピングする場合には,ワーキングセットの消費量に注意するようにしましょう.メモリアクセスのパターンによっては,一時的に大量な物理メモリが割り当てられる可能性があります.