Unexpected page processing (also VirtualLock = no op?)

This morning I came across an amazing amount of page errors, where I did not expect them. Yes, I probably should not worry, but it still seems strange to me, because, in my opinion, they should not happen. And, I would like it to be better if they did not.

The application (under WinXP Pro 32bit) reserves a large section (1 GB) of address space with VirtualAlloc(MEM_RESERVE), and then allocates moderately large blocks (20-50 MB) of memory with VirtualAlloc(MEM_COMMIT). This is done by the employee ahead of schedule, the goal is to delay the main flow as little as possible. Obviously, you can never guarantee that page errors will not occur if the memory area is currently locked, but some of them are certainly valid (and inevitable). Surprisingly, every page error. Is always.

Thus, the assumption was that the system selects pages only after they are selected, which also makes sense (although there is something else in the documentation). Fair enough, my bad.
Therefore, the obvious workaround is VirtualLock/ VirtualUnlock, which forces the system to create these pages, since they must exist after the return VirtualLock. Surprisingly, all errors are on every page.

So, I wrote a small test program that did all of the above steps sequentially, sleeping 5 seconds between them, to exclude that something was wrong in another code. Results:

  • MEM_RESERVE 1GB ---> success, zero processor, zero time, nothing happens
  • MEM_COMMIT 1 GB ---> success, zero processor, zero time, working set increased by 2 MB, 512 page errors (respectively 8 bytes of metadata allocated in user space per page)
  • for(... += 128kB) { VirtualLock(128kB); VirtualUnlock(128kB); } ---> success, zero processor, zero time, nothing happens
  • for(... += 4096) *addr = 0;---> 262144 page errors, about 0.25 seconds (~ 95% of the kernel time). 1 GB increase for working set and physical inside Process Explorer
  • VirtualFree ---> zero processor, zero time, both "working set" and "physical" instantly go * poof *.

, , , , , . , WS ( , ). , , , , , . , , . , , ?

, VirtualLock, - ? , ", , " , , , ?

UPDATE:
, , VirtualLock . , 200k/1M, , VirtualLock 200 . (, 200 ., , - ).

1 2 VirtualAlloc(MEM_COMMIT). " " Process Explorer 1 . , . , , "" , , , .

VirtualLock - ( ), .

WS. -, , , , . ( , ).
, SetProcessWorkingSetSize PROCESS_SET_QUOTA, "", ( ), " ?" - ( , , , ).

+5
3

VirtualLock - , . NtLockVirtualMemory, Reactos/Wine no-op, Windows (MiLockVadRange).

VirtualLock . , SE_LOCK_MEMORY_PRIVILEGE , . , VirtualUnlock ​​ , .

, , . , VirtualLock , , , .

+3

VirtualLock -op ( )

, , . , :

  • (523 )
  • (21 )
  • VirtualAlloc MEM_COMMIT 2500 (2 )
  • VirtualLock ( 641 250 )
  • ( )

, . 2500 - 640 000 . . , , VirtualAlloc, VirtualLock.

, VirtualLock, , no-op Win7 x64. , , , , . - 640 000 . , , .


, , , , .

. , , . , . , , . , , ...

, , RAM , , : VirtualLock VirtualUnlock - , .

. () , , . , . , , . , , .

, , , (, , ). , , , . .

, , Win7 x64 , , .


WS. -, , ,

... VirtualLock, . , SetProcessWorkingSetSize, . ; VirtualLock, , .


:

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    SIZE_T chunkSize = 2500LL * 1024LL * 1024LL; // 2,626,568,192 = 640,000 pages
    int sleep = 5000;

    Sleep(sleep);

    cout << "Setting working set size... ";
    if (!SetProcessWorkingSetSize(GetCurrentProcess(), chunkSize + 5001001L, chunkSize * 2))
        return -1;
    cout << "done" << endl;

    Sleep(sleep);

    cout << "VirtualAlloc... ";
    UINT8* data = (UINT8*) VirtualAlloc(NULL, chunkSize, MEM_COMMIT, PAGE_READWRITE);
    if (data == NULL)
        return -2;
    cout << "done" << endl;

    Sleep(sleep);

    cout << "VirtualLock... ";
    if (VirtualLock(data, chunkSize) == 0)
        return -3;
    //if (VirtualUnlock(data, chunkSize) == 0) // enable or disable to experiment with unlocks
    //    return -3;
    //if (!SetProcessWorkingSetSize(GetCurrentProcess(), 5001001L, chunkSize * 2))
    //    return -1;
    cout << "done" << endl;

    Sleep(sleep);

    cout << "Writes to the memory... ";
    while (true)
    {
        int* end = (int*) (data + chunkSize);
        for (int* d = (int*) data; d < end; d++)
            *d = (int) d;
        cout << "done ";
    }

    return 0;
}

, VirtualLock. 2007 Raymond Chen, OS , , MSDN , , , , . , , , . , 2007 , Win7.

+2

, .

, VirtualLock. , 2007 , [...] , 2007 , Win7.

romkyns, 2014 . , VirtualLock, , . , , , , .

, , , msdn

, , . , .

0

All Articles