Interioridades de la memoria de Windows (1.ª parte) — El instante en que una dirección virtual se convierte en RAM física: un Page Fault de principio a fin

· Actualizado el: · · Windows, Gestión de memoria, VirtualAlloc, Page Fault, VAD, Monitor de rendimiento

Historial de revisiones (primera versión, publicada el 20 Aug 2026)
Primera publicación
Citar este artículo(DOI (archivo registrado): 10.5281/zenodo.22176070)

Los DOI siguientes remiten a versiones ya archivadas y pueden diferir del texto actual. Para citar el texto actual, utilice la URL de esta página.

Go Komura (2026). Interioridades de la memoria de Windows (1.ª parte) — El instante en que una dirección virtual se convierte en RAM física: un Page Fault de principio a fin. KomuraSoft LLC. https://comcomponent.com/es/blog/windows-memory-internals-page-fault/

DOI (archivo registrado)
10.5281/zenodo.22176070
DOI (última versión registrada)
10.5281/zenodo.22176071

«Hice Commit de 256MiB, pero el Working Set no aumenta en la misma medida». Esa duda, que aparece al usar VirtualAlloc, es el punto de partida de la 1.ª parte.

En la memoria privada habitual, hacer Commit y colocar esa página en RAM física son cosas distintas. Windows retrasa la asignación de páginas físicas hasta que la aplicación toca de verdad la página. Cuando el primer acceso provoca un Page Fault, el administrador de memoria examina el VAD, la PTE, los atributos de protección y el backing store, y vincula la RAM necesaria página a página.1

Este artículo sigue el camino que recorre ese «primer byte tocado» hasta llegar a la RAM física. Si primero quiere aclarar el significado de cifras como Working Set o Commit, consulte el artículo introductorio «Qué representa el «uso de memoria» de Windows — cómo leer correctamente Working Set, Private Bytes, Commit y el archivo de paginación». Esta serie no redefine esos términos; profundiza desde el mecanismo en por qué esa cifra llega a ser la que es.

«Interioridades de la memoria de Windows»: las 3 partes

Esta serie avanza en el orden obtener una página física → seguir la residencia y la recuperación → entender el uso compartido y la privatización.

Parte Tema Lo que sigue esta parte
1.ª parte (este artículo) Direcciones virtuales y Page Fault Cuándo una región asignada con VirtualAlloc obtiene RAM física
2.ª parte La vida de una página física Las transiciones de estado de una página que sale del Working Set y el papel del archivo de paginación
3.ª parte Objetos de sección y copy-on-write Cómo las DLL, las asignaciones de archivos y la memoria compartida comparten páginas físicas

La 1.ª parte responde a una sola pregunta.

¿En qué instante una dirección virtual ya en Commit se convierte en RAM física?

Antes de empezar Contenido
Público Desarrolladores y responsables de operación que quieren entender, desde el mecanismo, el uso de memoria, los Page Fault justo después del arranque, 0xC0000005 y las cifras de VMMap o PerfMon
Entorno previsto Windows 10/11 o una versión actual de Windows Server
Conocimientos previos Fundamentos de punteros y de VirtualAlloc
Dificultad Intermedio. No hace falta experiencia con la disposición de bits de la tabla de páginas ni con el depurador de kernel

Se usan nombres de estructuras internas, pero no se asume ningún diseño no documentado que dependa de una compilación concreta de Windows.

En el diagrama, una línea continua marca una relación que siempre se cumple y una línea discontinua una relación condicional (las condiciones están en la explicación de cada relación en la página de detalle). La lista completa de relaciones (14 en total, con evidencia y grado de certeza) y las definiciones de los conceptos principales están reunidas en la página de detalle del mapa de conocimiento (en japonés). Datos: JSON-LD / Turtle

1. La conclusión primero

En la memoria privada habitual, si se separan las tres etapas siguientes, se ve la diferencia entre Commit y Working Set.

  1. Reserve es la etapa que reserva una dirección en el espacio virtual. Reserva el rango, pero no asigna almacenamiento físico en la RAM ni en el archivo de paginación.1
  2. Commit es la etapa en la que el sistema promete que podrá conservar el contenido en el futuro. Cobra una cuota de commit y aumenta el Commit Total, pero normalmente aún no vincula RAM física a todas las páginas.12
  3. Touch es la etapa en la que realmente hace falta una página física. El primer acceso provoca un Page Fault y, si el acceso es legítimo, el administrador de memoria asigna una página física y reejecuta la instrucción.

MEM_COMMIT no es una orden que diga «reserve RAM ahora mismo». Tampoco es una promesa vacía: es la promesa de todo el sistema de que en el futuro podrá conservar ese contenido en RAM o en el backing store adecuado. Que el contenido inicial de una página en Commit sea cero y que la página física no se asigne hasta el primer acceso son hechos compatibles.1

Tampoco es exacto entender que «Reserve/Commit solo escriben en el VAD». En Reserve se crea sobre todo un VAD que representa el rango y sus atributos; en Commit aumenta el Commit Total del sistema y se registra el estado de commit del rango. Los niveles intermedios de la tabla de páginas y cada PTE individual se construyen de forma diferida, cuando hacen falta.

Lo que quiere saber Sección a leer
Qué cambia en Reserve, Commit y Touch Secciones 2 a 3
Qué deciden el VAD, la PTE y el TLB Secciones 4 a 6
Separar los fault normales de la espera de E/S y de las excepciones Secciones 7 a 9
Comprobarlo con cifras en su propio equipo Secciones 10 a 11
Qué sucede en Reserve, Commit y el primer accesoMEM_RESERVE registra el rango y los atributos en el VAD, MEM_COMMIT consume el Commit Total para prometer el almacenamiento, y el Page Fault del primer acceso asigna la página física y la añade al Working Set1. MEM_RESERVE2. MEM_COMMIT3. Primer acceso (Touch)Registrar el rango y los atributos en el VADConsumir el Commit Total (aún sin página física)Page FaultVincular una página física puesta a cero a la PTEAñadir al Working Set y reejecutar la instrucción

Figura 1: Reserve, Commit y Touch son sucesos distintos. La RAM física se vincula en el último paso, el primer acceso.

2. Tres registros que siguen la página virtual

Los registros que mantiene Windows miran la misma memoria en unidades distintas. Primero separe los tres: rango, página virtual y página física.

Registro Unidad Función
VAD Rango de direcciones virtuales Gestiona de qué es la región, Reserve/Commit, la protección y la correspondencia con la sección
Tabla de páginas / PTE Página virtual Representa la traducción actual a una página física, o un estado aún no materializado
Base de datos PFN Página física Sigue la propiedad, las referencias y el estado de cada página de RAM

El VAD guarda información del rango, la PTE de la página virtual y la base de datos PFN de la página física. El controlador de Page Fault cruza estos datos para decidir si el acceso puede continuar.

Tres registros desde la dirección virtual hasta la RAM físicaLa dirección virtual la gestiona el VAD por rango y la PTE por página virtual, y la página física a la que traduce la PTE la sigue la base de datos PFN por página físicaEvalúa Reserve/Commit y protecciónTraducción válidaDirección virtualVAD (registro de rangos)PTE (registro de páginas virtuales)Base de datos PFN (registro de páginas físicas)Página de RAM física

Figura 2: Tres registros de distinta granularidad. El tratamiento del fault cruza el VAD y la PTE, y refleja el resultado en el lado del PFN.

Los protagonistas de este artículo son el VAD y la PTE. La base de datos PFN se aborda en la 2.ª parte desde el lado de la página física.

3. Reserve, Commit y Touch son sucesos distintos

3.1. Reserve — reservar la dirección

Primero, reserve un rango contiguo de direcciones virtuales de 256MiB.

void* base = VirtualAlloc(
    nullptr,
    256ull * 1024 * 1024,
    MEM_RESERVE,
    PAGE_NOACCESS);

Lo que ha ocurrido en este punto es solo que se ha reservado una dirección en el espacio virtual del proceso para que otras asignaciones no usen este rango. MEM_RESERVE no asigna almacenamiento físico ni en la RAM ni en el archivo de paginación.1

Como un proceso de 64 bits dispone de un espacio virtual enorme, resulta práctico un diseño que haga Reserve de un rango grande de antemano y luego haga Commit solo de las partes que necesita.

3.2. Commit — prometer que el contenido se puede conservar

A continuación, haga Commit del rango reservado.

void* committed = VirtualAlloc(
    base,
    256ull * 1024 * 1024,
    MEM_COMMIT,
    PAGE_READWRITE);

Si tiene éxito, aumenta la cantidad prometida, que se refleja en el Commit Total del sistema y, habitualmente, en los Private Bytes del proceso. Aun así, no se alinean de golpe 256MiB de páginas físicas. Las páginas ordinarias siguen sin asignarse físicamente hasta el primer acceso.12

¿Qué sentido tiene entonces el Commit? Que, si el sistema no puede asumir la promesa, puede devolver un error en el momento del Commit, y no a mitad de usar la memoria.

3.3. Touch — cuando hace falta una página física

Por último, la siguiente asignación escribe por primera vez en la página inicial.

static_cast<unsigned char*>(base)[0] = 1;

La CPU intenta traducir la dirección virtual a una dirección física, pero la PTE aún no tiene una traducción válida a una página física. Ahí se produce el Page Fault.

El administrador de memoria, que recibe el control, determina que se trata de «un primer acceso a una página privada en Commit y escribible», obtiene una página física puesta a cero, la vincula a la PTE y la añade al Working Set. Después hace que se vuelva a ejecutar la instrucción de escritura que falló.

Desde la aplicación solo se ve una asignación, pero por dentro el control entra en el kernel a mitad de la asignación, se asigna una página física y la ejecución vuelve a la misma instrucción.

4. El VAD — el registro de rangos del espacio virtual

VAD es la abreviatura de Virtual Address Descriptor, y Windows gestiona los rangos de direcciones en uso de un proceso como un árbol de VAD. Con el comando !vad de WinDbg se pueden consultar la VPN de inicio y de fin, el Commit, los atributos de protección, Private/Mapped, el Control Area y más.3

La información representativa que expresa un VAD es la siguiente.

  • El inicio y el fin del rango de direcciones
  • El tipo: Private, Mapped, Image, etc.
  • El estado Reserve/Commit
  • La protección: lectura, escritura, ejecución, Copy-on-Write, etc.
  • La correspondencia con un archivo o una sección
  • Atributos especiales como las páginas de guarda

Se guarda por rango para reducir el coste de gestión. 256MiB equivalen a 65.536 páginas de 4KiB.

En lugar de construir desde el principio una estructura de gestión completa para cada página, el VAD gestiona «este rango contiguo es una sola reserva». A partir de ahí, las páginas se materializan cuando hacen falta.

4.1. Encontrar un VAD no garantiza que se pueda recuperar

La explicación «si está en un VAD se resuelve el fault; si no, hay violación de acceso» es cómoda como puerta de entrada, pero simplifica demasiado. Aunque se encuentre un VAD, el acceso ordinario no puede continuar, por ejemplo, en casos como estos.

  • Solo se hizo Reserve y la página objetivo no está en Commit
  • Es PAGE_NOACCESS
  • Se escribió en una página de solo lectura
  • Se ejecutó una instrucción desde una página no ejecutable
  • Se tocó por primera vez una página de guarda
  • Se tocó fuera del rango válido de una sección

Al contrario, aunque la PTE sea inválida, si el estado de software del VAD y de la PTE indica que el acceso es legítimo, se puede resolver como demand-zero, restauración desde Transition, page-in o CoW. Con precisión, la respuesta es evaluar juntos el VAD, la PTE, los atributos de protección y el tipo de acceso.

5. Tablas de páginas y TLB

El puntero que tiene la aplicación es una dirección virtual. Para que la CPU acceda a la RAM, debe traducir el número de página virtual al número de página física. Esa tabla jerárquica de traducción es la tabla de páginas, y la entrada de hoja es la PTE (Page Table Entry).

Una PTE válida tiene, en concepto, el PFN, la protección de lectura, escritura y ejecución, si se permite el modo usuario, Accessed/Dirty y datos similares. La disposición real de los bits depende de la CPU y de la versión de Windows.

Aun así, recorrer la tabla de páginas cada vez sería demasiado lento, así que la CPU guarda en caché las traducciones recientes en el TLB (Translation Lookaside Buffer). La traducción de direcciones avanza en este orden.

  1. Si el TLB tiene la traducción y el acceso se ajusta a su protección, se usa ese resultado.
  2. Si el TLB no tiene la traducción, la CPU recorre la tabla de páginas.
  3. Si hay una PTE válida y el acceso también se ajusta a la protección, se registra en el TLB y se continúa.
  4. Si no hay una traducción válida, o hay una violación de protección, se pasa al punto de entrada del Page Fault. La comprobación de protección se hace también cuando la traducción viene del TLB.

Lo que aquí se confunde con facilidad es que un fallo de TLB y un Page Fault son cosas distintas.

Situación Qué ocurre a continuación
El TLB tiene la traducción y el acceso se ajusta a la protección Continuar con la traducción en caché
El TLB no tiene la traducción, pero hay una PTE válida y el acceso se ajusta a la protección Obtener la traducción con un recorrido de la tabla de páginas y continuar
No hay traducción válida, o se viola la protección Pasar al punto de entrada del Page Fault

La comprobación de protección también actúa en un acierto de TLB. Una escritura en una página de solo lectura, o la ejecución de una instrucción en una página no ejecutable, provoca un fault aunque la traducción ya esté en caché. Por eso también puede producir un fault una escritura en una página CoW.

Flujo de traducción de direcciones y punto de entrada del Page FaultAunque el TLB tenga la traducción, si el acceso no se ajusta a la protección se pasa al punto de entrada del Page Fault. Si el TLB no tiene la traducción se recorre la tabla de páginas; una PTE válida cuya protección también se cumple se registra en el TLB y se continúa, y una traducción inválida o una violación de protección pasa al punto de entrada del Page FaultSíSe ajustaViolación de protecciónNoSíInválida o violación de protecciónAcceso a memoria¿El TLB tiene la traducción?¿Se ajusta a la protección?Continuar con esa traducciónAl punto de entrada del Page FaultRecorrido de la tabla de páginas¿PTE válida y la protección también se cumple?Registrar en el TLB y continuar (sin fault)

Figura 3: Un fallo de TLB se puede resolver con un recorrido de la tabla de páginas. Se pasa a un Page Fault cuando la traducción es inválida o hay una violación de protección, y la violación de protección también ocurre en un acierto de TLB.

5.1. Una PTE inválida no es un simple hueco vacío

Que una PTE sea inválida no significa que su contenido esté vacío. A partir del estado de software de una PTE inválida, Windows distingue, por ejemplo, casos como estos.

  • Una página de demand-zero que nunca se ha materializado
  • Una página Transition que permanece en RAM
  • Una página compartida que apunta a una Prototype PTE
  • Una página privada guardada en el archivo de paginación
  • Una violación de protección o una región inválida

El trabajo de la CPU termina en decidir «esta no es una traducción válida ordinaria» y pasarla al kernel; el significado a partir de ahí lo pone el administrador de memoria.

6. Un Page Fault de principio a fin

Sigamos en seis etapas la primera escritura en una página privada en Commit.

  1. La CPU intenta escribir.
    Consulta el TLB y la tabla de páginas, pero la PTE objetivo no tiene un PFN válido.
  2. La CPU genera un Page Fault.
    Pasa al kernel la dirección virtual del fault, el tipo de lectura, escritura o ejecución, usuario/kernel, y si la causa es la ausencia de traducción o una violación de protección.
  3. El administrador de memoria examina el VAD y la PTE.
    Decide si está en Commit, si se ajusta a la protección, y cuál de demand-zero, Transition, compartida, page-in, CoW o excepción corresponde.
  4. Si es demand-zero, obtiene una página física puesta a cero.
    Una página que se entrega de nueva debe ser cero para no filtrar datos de otro proceso.
  5. Actualiza la PTE y la información de gestión del PFN.
    Establece el PFN y la protección en la PTE, pone la página física en Active y la añade al Working Set del proceso.
  6. Reejecuta la instrucción que falló.
    Como se resolvió con normalidad, no llega ninguna excepción de modo usuario, y la aplicación continúa como si fuera una asignación ordinaria.

Los eventos de Page Fault de ETW también registran como tipos distintos Transition, Demand Zero, Copy-on-Write, Guard Page, Hard Page Fault y Access Violation.4

Es decir, Page Fault no es una palabra que signifique «anomalía» desde el principio. Es el punto de entrada común para pedir al sistema operativo que decida cuando la CPU no pudo traducir por la vía ordinaria.

Ramificación del destino de resolución de un Page FaultEl administrador de memoria evalúa el VAD, la PTE, los atributos de protección y el tipo de acceso, y reparte hacia demand-zero, reconexión de una página que sigue en RAM, hard fault desde un backing store, copy-on-write, notificación de página de guarda o excepciónPrimer accesoSigue en RAMHace falta leer discoEscritura CoWPágina de guardaIrresolubleSe produce el Page FaultEvaluar VAD, PTE, protección y tipoDemand-zero (soft)Reconectar desde Standby, etc. (soft)Hard fault (E/S de disco)Copiar y sustituir la PTEQuitar la guarda y notificarExcepción (0xC0000005, etc.)

Figura 4: Los fault que entran por el mismo punto se ramifican hacia seis desenlaces según el resultado de la evaluación. El detalle de las páginas de guarda se trata en la sección 9.

7. Demand-zero — un soft fault que no lee el disco

Demand-zero es el soft fault representativo que ocurre al tocar por primera vez una página privada en Commit. La documentación de Working Set de Microsoft también cita como ejemplo de soft fault el caso en que «el proceso referencia por primera vez una página virtual ya asignada».5

Demand-zero tiene las siguientes características.

  • No hace falta leer datos originales del disco
  • El contenido inicial es cero
  • Se vincula una página física disponible
  • Aumentan el Working Set y el Page Fault Count acumulado
  • Este tratamiento por sí solo no aumenta Memory\\Pages Input/sec

Por eso, que Page Faults/sec se dispare justo después del arranque no basta para decir que el almacenamiento está saturado.

7.1. La asignación diferida intercambia RAM por el coste del primer acceso

Si hace Commit de 256MiB pero en la práctica solo usa 8MiB, la asignación diferida, que evita colocar en RAM los 248MiB restantes, es razonable. A cambio, el primer acceso lleva el coste del tratamiento del fault.

En un trabajo con latencia estricta, a veces se elige un «prefault»: tocar cada página antes de empezar. No es una optimización gratuita. Es la decisión de adelantar el tratamiento del primer acceso a cambio de aumentar también de antemano la residencia en RAM.

8. Soft faults y hard faults

La frontera de la decisión es si hace falta una E/S de lectura desde un backing store. El número de Page Fault por sí solo no revela esa diferencia.

8.1. Soft faults

Un soft fault es un fault que se puede resolver sin E/S de lectura hacia un backing store. Ejemplos representativos:

  • Demand-zero
  • Reconexión de una página que permanece en Standby/Transition
  • Conexión de una página compartida que está en el Working Set de otro proceso
  • Conexión de una página ya leída por anticipado
  • Copy-on-Write cuya página original está residente

Hay coste de CPU por la transición al kernel, los bloqueos, las actualizaciones de PTE/PFN, la coherencia del TLB y similares, pero no hay espera de almacenamiento.5

8.2. Hard faults

En cambio, cuando la página necesaria no está en ningún sitio de la RAM y hay que leerla de un backing store, es un hard fault. El origen de la lectura no es solo el archivo de paginación.

  • Una página privada volcada al archivo de paginación
  • Un archivo asignado en memoria
  • Una imagen de EXE o DLL
  • Un archivo de datos al que apunta la caché de archivos

El evento HardFault de ETW incluye FileObject, ReadOffset y ByteCount, de modo que se puede seguir el origen real de la lectura.6

Por tanto, Hard Fault = se leyó pagefile.sys no es cierto.

Cuando hace falta leer el backing store, la petición entra en la pila de E/S de Windows. El flujo de IRP y de emisión y finalización se trata en «Las profundidades de la E/S de Windows (1.ª parte)», y la confluencia con la caché de archivos en «Las profundidades de la E/S de Windows (4.ª parte)». Si la página está en RAM, el administrador de memoria puede volver por sí solo; si no, emite E/S y hace esperar al subproceso del fault hasta que termine.

9. Un fault irresoluble se convierte en excepción

Un fault que, aun examinando el VAD y la PTE, no se puede resolver como una asignación legítima, un page-in o un CoW, se entrega al modo usuario como excepción.

9.1. Cuando se convierte en violación de acceso

El caso representativo es STATUS_ACCESS_VIOLATION, código de excepción 0xC0000005. Se produce al leer, escribir o ejecutar una dirección inválida; el primer parámetro de la excepción indica el tipo de acceso y el segundo, la dirección que violó la protección.7

Los patrones típicos de aparición son los siguientes.

  • Leer NULL, una dirección ya liberada o una dirección fuera de un array
  • Escribir en una página de solo lectura
  • Ejecutar una instrucción desde una página que DEP/NX ha marcado como no ejecutable
  • Tocar un rango en Reserve que no está en Commit

9.2. La página de guarda se usa como notificación de una sola vez

PAGE_GUARD tiene un significado un poco distinto. Es un mecanismo que notifica el acceso una sola vez, genera STATUS_GUARD_PAGE_VIOLATION y se usa, por ejemplo, para la expansión de la pila.8

La asignación diferida normal, el page-in, el CoW, la notificación de guarda y, al final, la violación de acceso: vistos desde la CPU, todos convergen en el mismo punto de entrada del Page Fault. Lo que decide el desenlace es la combinación del VAD, la PTE, los atributos de protección y el tipo de acceso.

10. Compruébelo con sus propios ojos

El objetivo del experimento es observar por separado la etapa en que aumenta el Commit y la etapa en que aumenta el Working Set.

El siguiente programa en C++ hace Reserve de 256MiB, hace Commit, escribe 1 byte en cada página y al final hace Release. En cada etapa espera la tecla Intro, de modo que ahí puede comprobar los valores de VMMap y de PerfMon.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>

#include <cstdio>
#include <cstdlib>

#pragma comment(lib, "Psapi.lib")

constexpr SIZE_T kSize = 256ull * 1024 * 1024;

void PrintMemory(const char* stage)
{
    PROCESS_MEMORY_COUNTERS_EX c{};
    c.cb = sizeof(c);
    if (!GetProcessMemoryInfo(
            GetCurrentProcess(),
            reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&c),
            sizeof(c))) {
        std::printf("GetProcessMemoryInfo failed: %lu\n", GetLastError());
        return;
    }

    std::printf(
        "%-10s WS=%zu MiB  Private=%zu MiB  Faults=%lu\n",
        stage,
        c.WorkingSetSize / 1024 / 1024,
        c.PrivateUsage / 1024 / 1024,
        c.PageFaultCount);
}

void Pause(const char* message)
{
    PrintMemory(message);
    std::puts("Press Enter...");
    (void)std::getchar();
}

int main()
{
    SYSTEM_INFO si{};
    GetSystemInfo(&si);
    std::printf("PID=%lu, page=%lu bytes\n",
                GetCurrentProcessId(), si.dwPageSize);

    void* base = VirtualAlloc(nullptr, kSize, MEM_RESERVE, PAGE_NOACCESS);
    if (!base) {
        std::fprintf(stderr, "Reserve failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("reserved");

    if (!VirtualAlloc(base, kSize, MEM_COMMIT, PAGE_READWRITE)) {
        std::fprintf(stderr, "Commit failed: %lu\n", GetLastError());
        VirtualFree(base, 0, MEM_RELEASE);
        return EXIT_FAILURE;
    }
    Pause("committed");

    auto* bytes = static_cast<volatile unsigned char*>(base);
    for (SIZE_T offset = 0; offset < kSize; offset += si.dwPageSize) {
        bytes[offset] = 1;
    }
    Pause("touched");

    if (!VirtualFree(base, 0, MEM_RELEASE)) {
        std::fprintf(stderr, "Release failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("released");
}

En el x64 Native Tools Command Prompt de Visual Studio, se puede compilar con el siguiente comando.

cl /std:c++20 /EHsc /W4 memory_fault_demo.cpp

10.1. Qué mirar en VMMap

VMMap es una herramienta que muestra, por tipo, la memoria virtual reservada, el Commit, el Working Set, Private y Shareable.9 El cambio esperado en cada etapa es el siguiente.

Etapa Cambio esperado
Reserve Aumenta Size de Address Space, pero Commit/WS no aumentan en la misma medida
Commit El Commit de Private aumenta unos 256MiB
Touch Working Set y Private WS aumentan de forma notable, y también aumenta Fault Count
Release Desaparece el rango objetivo y bajan Commit y WS

No busque coincidencia numérica; mire el cambio entre etapas

Las cifras reales varían con el runtime, el software de seguridad, la presión de memoria y el momento de la observación. No se trata de si sale exactamente 256MiB, sino de hacia dónde se movió entre una etapa y la siguiente.

10.2. Separar soft y hard con PerfMon

En PerfMon, coloque en el mismo eje temporal los siguientes contadores.

  • Process(<objetivo>)\\Page Faults/sec
  • Memory\\Pages Input/sec
  • Memory\\Page Reads/sec
  • Memory\\Available MBytes
  • Process(<objetivo>)\\Working Set - Private
  • Process(<objetivo>)\\Private Bytes

Process\\Page Faults/sec incluye tanto soft como hard. En cambio, Memory\\Pages Input/sec es el número de páginas leídas del disco para resolver hard faults.10

En la etapa Touch de este programa, Page Faults/sec debería dispararse sin que Pages Input/sec aumente de forma notable. Las páginas nuevas en Commit se materializan por demand-zero, así que no hace falta leer datos originales del disco.

Si hay varios procesos del mismo nombre, confirme también el PID

Si hay varios procesos con el mismo nombre, el número de process#1 y similares de PerfMon puede cambiar al reiniciar. Contrástelo con un contador que muestre el PID, o identifique por PID con Process V2 o ETW/WPA.

11. Tres lecturas erróneas que conviene evitar en la práctica

11.1. «Si aumentó el Commit, hay una fuga de RAM»

Commit es la cantidad prometida para conservar el contenido; las páginas aún no tocadas pueden no estar residentes en RAM. Para juzgar una fuga, mire la evolución temporal de Private Bytes, el desglose de las asignaciones y si, al terminar el trabajo, vuelve al valor de referencia.

11.2. «Si Page Faults/sec es alto, el disco es lento»

Un soft fault no implica E/S de disco. Separe Page Faults/sec, Pages Input/sec y la espera de almacenamiento y, si hace falta, siga con el evento HardFault de ETW hasta el archivo de origen de la lectura y la pila.

11.3. «Si vacío el Working Set, se corrige la fuga»

Sacar una página del Working Set no libera el Commit ni la propiedad. La página pasa a Standby o Modified y más tarde vuelve con un fault. Para corregir una fuga, quien la asignó tiene que hacer VirtualFree, liberar el montón, destruir el objeto, etc.

Adónde va esa página física una vez extraída se sigue en la 2.ª parte.

12. Resumen

  • MEM_RESERVE reserva un rango de direcciones virtuales, pero no asigna almacenamiento físico en la RAM ni en el archivo de paginación.1
  • MEM_COMMIT consume Commit y garantiza que el contenido se podrá conservar en el futuro, pero las páginas físicas habituales no se asignan hasta el primer acceso.12
  • El VAD es el registro de rangos, la PTE el de páginas virtuales y la base de datos PFN el de páginas físicas.
  • Un fallo de TLB no es un Page Fault. Si hay una PTE válida, se resuelve solo con un recorrido de la tabla de páginas.
  • Demand-zero, la restauración desde Transition y la conexión de una página compartida son soft faults que se resuelven sin E/S de disco.5
  • Si hace falta leer del archivo de paginación, una DLL, un EXE o un archivo asignado, es un hard fault.6
  • Si al examinar el VAD, la PTE y los atributos de protección no se puede resolver, se produce una excepción como 0xC0000005.7
  • Para evaluar el rendimiento, no se fije solo en Page Faults/sec: observe en el mismo eje temporal Pages Input/sec, Available, Working Set, Private Bytes y la espera de almacenamiento.

La continuación es la 2.ª parte, «La vida de una página física: las cinco listas y la verdad sobre el archivo de paginación».

Tras convertir la promesa de Commit en una página física, se sigue, a partir de la base de datos PFN y de las listas de páginas, adónde va esa página cuando sale del Working Set.

Artículos relacionados

Áreas de consulta relacionadas

En KomuraSoft LLC nos ocupamos de la investigación del uso de memoria de aplicaciones Windows, las violaciones de acceso, la lentitud en el arranque, la paginación y el análisis de defectos en código nativo.

Referencias

  1. Microsoft Learn, VirtualAlloc function. Sobre cómo MEM_RESERVE reserva un rango de direcciones virtuales sin asignar almacenamiento físico, cómo MEM_COMMIT cobra una cuota de commit contra la memoria y el archivo de paginación de todo el sistema, cómo el contenido inicial de una página en Commit es cero, y cómo la página física real no se asigna hasta que se accede a ella. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  2. Microsoft Learn, PERFORMANCE_INFORMATION structure. Sobre cómo CommitTotal es el número actual de páginas en Commit del sistema y CommitLimit es el límite máximo de Commit posible sin ampliar el archivo de paginación. ↩ ↩2 ↩3

  3. Microsoft Learn, !vad (WinDbg). Sobre cómo !vad muestra el árbol de VAD y permite consultar la VPN de inicio y de fin, el Commit, Mapped/Private, los atributos de protección, el Control Area y más. ↩

  4. Microsoft Learn, PageFault_TypeGroup1 class. Sobre cómo ETW distingue y registra Transition Fault, Demand Zero Fault, Copy-on-Write, Guard Page Fault, Hard Page Fault y Access Violation. ↩

  5. Microsoft Learn, Working Set. Sobre cómo un soft fault se puede resolver sin acceder al backing store, y cómo ocurre por el Working Set de otro proceso, por Transition o por demand-zero en la primera referencia, entre otros casos. ↩ ↩2 ↩3

  6. Microsoft Learn, PageFault_HardFault class. Sobre cómo el evento HardFault incluye FileObject, ReadOffset, ByteCount, VirtualAddress y Thread ID, lo que permite rastrear el origen de la lectura. ↩ ↩2

  7. Microsoft Learn, Access Violation C0000005. Sobre cómo 0xC0000005 se produce al leer, escribir o ejecutar una dirección de memoria inválida, y cómo los parámetros de la excepción indican el tipo de acceso y la dirección que violó la protección. ↩ ↩2

  8. Microsoft Learn, Creating Guard Pages. Sobre cómo PAGE_GUARD proporciona una notificación de un solo uso del acceso a la página y genera STATUS_GUARD_PAGE_VIOLATION. ↩

  9. Microsoft Learn, VMMap - Sysinternals. Sobre cómo VMMap descompone la memoria virtual en Commit por tipo y muestra el Working Set y el mapa de direcciones detallado de cada tipo. ↩

  10. Microsoft Learn, Performance Analysis of Logs (PAL) Tool. Sobre cómo Memory\\Pages Input/sec es el número de páginas leídas del disco para resolver hard Page Fault. ↩

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Se reserva RAM en el momento en que VirtualAlloc hace MEM_COMMIT?
En la memoria privada habitual, el Commit consume la capacidad de commit del sistema, pero la página física correspondiente no se asigna hasta el primer acceso. La página que se toca por primera vez con una escritura obtiene su página física durante el tratamiento de un fault de demand-zero.
¿Un Page Fault significa una anomalía o un problema de rendimiento?
No. Los soft faults que no implican E/S de disco, como el demand-zero o la recuperación desde Standby, son comportamiento normal. Para evaluar el rendimiento no basta con Page Faults/sec: hay que observarlo junto con Pages Input/sec, la espera de almacenamiento y Available MBytes.
¿Un fallo de TLB es lo mismo que un Page Fault?
Son cosas distintas. Aunque el TLB no tenga la traducción, si la PTE de la tabla de páginas es válida, la CPU simplemente recorre la tabla y vuelve a registrar la traducción. Solo se entra en el Page Fault cuando la PTE es inválida o hay una violación de protección.
¿Si el VAD tiene el rango de direcciones, no se produce una violación de acceso?
No necesariamente. Además de si existe un VAD, el administrador de memoria evalúa si el rango está en Reserve o en Commit, los atributos de protección de lectura, escritura y ejecución, las páginas de guarda y el estado de la PTE, entre otros factores. Si no puede resolverse, se produce una excepción como 0xC0000005.
¿Un valor alto de Page Faults/sec indica falta de RAM?
Eso solo no permite concluirlo. Page Faults/sec también incluye un gran volumen de soft faults. Es necesario correlacionarlo, en el mismo eje temporal, con Memory\Pages Input/sec, Memory\Page Reads/sec, Available MBytes y el tiempo de espera de disco.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog