Неожиданная обработка страницы (также VirtualLock = no op?)

Этим утром я наткнулся на удивительное количество ошибок страниц, где я их не ожидал. Да, я, наверное, не должен волноваться, но это все равно кажется мне странным, потому что в моем понимании они не должны происходить. И я бы хотел лучше, если бы они этого не сделали.

Приложение (под WinXP Pro 32bit) резервирует больший раздел (1 ГБ) адресного пространства сVirtualAlloc(MEM_RESERVE) и позже выделяет умеренно большие блоки (20-50 МБ) памяти сVirtualAlloc(MEM_COMMIT), Это делается на рабочем месте раньше времени с намерением остановить основной поток как можно меньше. Очевидно, что вы никогда не сможете гарантировать, что сбои страниц не произойдут, если область памяти в данный момент не заблокирована, но некоторые из них, безусловно, терпимы (и неизбежны). Как ни страннокаждая страница разломы. Всегда.

Таким образом, предполагалось, что система только лениво создает страницы после их распределения, что также имеет смысл (хотя документация предлагает что-то другое). Справедливо, мой плохой.
Поэтому очевидный обходной путьVirtualLock/VirtualUnlock, что заставляет систему создавать эти страницы, так как онидолжен существовать послеVirtualLock возвращается. Как ни странно,по-прежнему каждая страница неисправна.

Поэтому я написал небольшую тестовую программу, которая выполняла все вышеперечисленные шаги последовательно, спя по 5 секунд между ними, чтобы исключить что-то не так в другом коде. Результаты были:

MEM_RESERVE 1GB ---> успех, ноль ЦП, ноль времени, ничего не происходитMEM_COMMIT 1 ГБ ---> успех, ноль ЦП, ноль времени, увеличение рабочего набора на 2 МБ, 512 сбоев страниц (соответственно 8 байтов метаданных, выделенных в пространстве пользователя на страницу)for(... += 128kB) { VirtualLock(128kB); VirtualUnlock(128kB); } ---> успех, ноль ЦП, ноль времени, ничего не происходитfor(... += 4096) *addr = 0; ---> 262144 сбоев страницы, около 0,25 секунды (~ 95% времени ядра). Увеличение на 1 ГБ как для «рабочего набора», так и для «физического» в Process ExplorerVirtualFree ---> нулевой процессор, нулевое время, оба «рабочий набор» и «физический» мгновенно переходят в * poof *.

Я ожидал, что, поскольку каждая страница была заблокирована один раз, она должна существовать физическипо крайней мере, после этого, Конечно, он может все еще перемещаться в WS и из WS при превышении квоты (простое изменение одной ссылки, если доступно достаточно оперативной памяти). Тем не менее, ни время выполнения, ни рабочий набор, ни показатели физической памяти, кажется, не поддерживают это. Скорее, как кажется, каждая отдельная доступная страница создается при сбое, даже если она была заблокирована ранее. Конечно яМожно трогать каждую страницу вручную в рабочем потоке, но должен быть и чище путь?

Я делаю неправильное предположение о том, чтоVirtualLock должен делать или я не понимаю что-то правильно о виртуальной памяти? Любая идея о том, как сказать ОС «чистым, законным, работающим» способом, что я буду нуждаться в памяти, и я буду хотеть этосерьезно?

ОБНОВИТЬ:
В ответ на предложение Гарри Джонстона я попробовал несколько проблемный подходVirtualLock на гигабайт памяти. Чтобы это было успешным, вы должны сначала соответственно установить размер рабочего набора процесса, так как квоты по умолчанию составляют 200k / 1M, что означаетVirtualLock не может заблокировать область размером более 200 КБ (или, скорее, он не может заблокировать более 200 КБвсе вместеи это минус того, что уже заблокировано для ввода / вывода или по другой причине).

После установки минимального размера рабочего набора 1 ГБ и максимум 2 ГБ все сбои страниц происходят в тот момент,VirtualAlloc(MEM_COMMIT) называется. «Виртуальный размер» в Process Explorer мгновенно увеличивается на 1 ГБ. До сих пор это выглядело очень, очень хорошо.
Однако, если присмотреться, то «физическое» остается таким, как есть, реальная память действительно используется только в тот момент, когда вы касаетесь ее.

VirtualLock остается неработоспособным (в случае ошибки), но с увеличением минимального размера рабочего набораЧто-то вроде приблизился к цели.

Однако есть две проблемы с изменением размера WS. Во-первых, у вас обычно не должно быть гигабайта минимального рабочего набора в процессе, потому что ОС старается сохранить этот объем памяти заблокированным. Это было бы приемлемо в моем случае (на самом деле это более или менее то, что я прошу).
Большая проблема в том, чтоSetProcessWorkingSetSize нуждается вPROCESS_SET_QUOTA право доступа, которое не является проблемой «администратора», но не работает, когда вы запускаете программу как пользователь с ограниченными правами (по уважительной причине), и вызывает «разрешить возможно вредоносную программу?» Оповещение о некоторых известных российских антивирусных программ (длянет веская причина, но увы, вы не можете выключить его).

Ответы на вопрос(3)

Ваш ответ на вопрос