Manejo inesperado de la página (también, VirtualLock = no op?)

Esta mañana me topé con un sorprendente número de fallas de página donde no las esperaba. Sí, probablemente no debería preocuparme, pero aún así me parece extraño, porque, según tengo entendido, no deberían suceder. Y me gustaría más si no lo hicieran.

La aplicación (bajo WinXP Pro 32bit) reserva una sección más grande (1GB) de espacio de direcciones conVirtualAlloc(MEM_RESERVE) y luego asigna bloques moderadamente grandes (20-50MB) de memoria conVirtualAlloc(MEM_COMMIT). Esto se hace con anticipación en un trabajador, con la intención de detener el hilo principal lo menos posible. Obviamente, nunca se puede asegurar que no ocurran fallas en la página a menos que la región de memoria esté actualmente bloqueada, pero algunas de ellas son ciertamente tolerables (e inevitables). Sorprendentemente cada página individual fallas. Siempre

Por lo tanto, se suponía que el sistema solo crea páginas perezosamente después de asignarlas, lo que de alguna manera también tiene sentido (aunque la documentación sugiere algo diferente). Bastante justo, mi mal.
La solución obvia es, por lo tanto,VirtualLock/VirtualUnlock, que obliga al sistema a crear esas páginas, ya quedeb existe después deVirtualLock devoluciones. Sorprendentemente,todos los errores de cada página.

Así que escribí un pequeño programa de prueba que hizo todos los pasos anteriores en secuencia, durmiendo 5 segundos entre cada uno, para descartar que algo estuviera mal en el otro código. Los resultados fueron:

MEM_RESERVE 1GB ---> éxito, cero CPU, cero tiempo, no pasa nadaMEM_COMMIT 1 GB ---> éxito, cero CPU, tiempo cero, el conjunto de trabajo aumenta en 2 MB, fallas de 512 páginas (respectivamente 8 bytes de metadatos asignados en el espacio de usuario por página)for(... += 128kB) { VirtualLock(128kB); VirtualUnlock(128kB); } ---> éxito, cero CPU, cero tiempo, no pasa nadafor(... += 4096) *addr = 0; ---> 262144 fallas de página, aproximadamente 0.25 segundos (~ 95% del tiempo de kernel). Aumento de 1 GB para "conjunto de trabajo" y "físico" dentro de Process ExplorerVirtualFree ---> CPU cero, tiempo cero, tanto el "conjunto de trabajo" como el "físico" se vuelven instantáneamente * poof *.

Mi expectativa era que, dado que cada página se había bloqueado una vez, debe existir físicamente al menos después de eso. Por supuesto, aún podría moverse dentro y fuera del WS a medida que se excede la cuota (simplemente cambiando una referencia siempre que haya suficiente RAM disponible). Sin embargo, ni el tiempo de ejecución, ni el conjunto de trabajo, ni las métricas de memoria física parecen apoyar esto. Por el contrario, según parece, cada página a la que se accede se crea al generar un error, incluso si se había bloqueado anteriormente. Por supuesto yolat toca cada página manualmente en un hilo de trabajo, pero ¿debe haber una forma más limpia también?

Estoy haciendo una suposición errónea sobre lo queVirtualLock deberí ¿Entiendo o no entiendo algo correcto sobre la memoria virtual? Alguna idea sobre cómo decirle al sistema operativo de una manera "limpia, legítima y funcional" que voy a querer memoria, y la querréde verda?

ACTUALIZAR
n reacción a la sugerencia de Harry Johnston, probé el enfoque algo problemático de llamar aVirtualLock en un gigabyte de memoria. Para que esto tenga éxito, primero debe establecer el tamaño del conjunto de trabajo del proceso en consecuencia, ya que las cuotas predeterminadas son 200k / 1M, lo que significaVirtualLock no puede bloquear una región mayor de 200k (o mejor dicho, no puede bloquear más de 200ktodos junto, y eso es menos lo que ya está bloqueado para E / S o por otra razón).

Después de establecer un tamaño de conjunto de trabajo mínimo de 1 GB y un máximo de 2 GB, todas las fallas de página ocurren en el momentoVirtualAlloc(MEM_COMMIT) se llama. El "tamaño virtual" en Process Explorer aumenta 1GB al instante. Hasta ahora, se veía muy, muy bien.
Sin embargo, mirando más de cerca, "Físico" permanece como está, la memoria real solo se usa en el momento en que la tocas.

VirtualLock sigue siendo un no-op (sabio), pero eleva el tamaño mínimo del conjunto de trabajomas o meno se acercó a la meta.

Sin embargo, hay dos problemas con la manipulación del tamaño de WS. En primer lugar, generalmente no se supone que tenga un gigabyte de conjunto de trabajo mínimo en un proceso, porque el sistema operativo se esfuerza por mantener esa cantidad de memoria bloqueada. Esto sería aceptable en mi caso (en realidad es más o menos justo lo que pido).
El mayor problema es queSetProcessWorkingSetSize necesita elPROCESS_SET_QUOTA derecho de acceso, que no es un problema como "administrador", pero falla cuando ejecuta el programa como usuario restringido (por una buena razón), y activa el "¿Permitir programa posiblemente dañino?" alerta de un conocido software antivirus ruso (paraN buena razón, pero por desgracia, no puede apagarlo).

Respuestas a la pregunta(3)

Su respuesta a la pregunta