Windows dice que la RAM se agotó mientras todavía hay 4 GB de memoria física disponible

24

Captura de pantalla de la información del sistema de Process Explorer

Esta información del sistema es de Process Explorer. Todavía hay memoria física disponible, pero el sistema muestra que casi no queda RAM.

El Administrador de tareas también muestra que se usa alrededor del 74% de la RAM total.

Desde la instalación de Windows 8.1, la computadora tenía 4 + 8 = 12 GB de RAM. Lo actualicé cambiando los 4 GB a un módulo de 8 GB. ¿Podría ser el problema? ¿O es este comportamiento normal y acabo de entender mal el significado de la memoria física disponible?

usuario471487
fuente
La imagen que intentaba adjuntar está aquí: tinypic.com/view.php?pic=npon5c&s=8#.Va3P3_lVhBc . Aprobé una edición para agregar esta URL, pero eso aparentemente no es suficiente.
Jamie Hanrahan
@JamieHanrahan: las imágenes deben cargarse utilizando el Ctrl+Gacceso directo para que Stack Exchange pueda evitar que se pudran con el tiempo.
Deltik
@Deltik No fue mi imagen subir.
Jamie Hanrahan
@JamieHanrahan - Una vez que se envió la pregunta, se le asignó una licencia al material, la imagen es las comunidades en este punto ..
Ramhound
Destacado para futuras referencias, gracias. Simplemente vi el enlace al sitio tinypic en una edición propuesta, y aprobé esa edición, pero eso no tuvo ningún efecto.
Jamie Hanrahan

Respuestas:

65

Respuesta corta

La ventana emergente "sin memoria" dice que se está agotando el límite de memoria privada comprometida , un tipo de memoria virtual. No es que te estés quedando sin RAM (memoria física). No importa la cantidad de RAM disponible que tenga. Tener mucha RAM disponible no le permite superar el límite de confirmación. El límite de confirmación es la suma de su RAM total (¡esté en uso o no!) Más el tamaño actual de su archivo de paginación.

Por el contrario, ¡qué límite de compromiso de "uso" (que es principalmente la creación de espacio de direcciones virtuales privado de proceso) no necesariamente usa RAM! Pero el sistema operativo no permitirá su creación a menos que sepa que hay algún lugar para almacenarlo si alguna vez lo necesita. Por lo tanto, puede ejecutar el límite de confirmación sin utilizar toda su RAM, o incluso la mayor parte de su RAM.

Es por eso que no debe ejecutarse sin un archivo de paginación. Tenga en cuenta que el archivo de paginación podría no estar escrito en realidad. Pero aún así le permitirá evitar los errores de "poca memoria" y "falta de memoria".

Respuesta intermedia

Windows en realidad no tiene un mensaje de error por quedarse sin RAM. De lo que se está quedando sin "límite de compromiso".

El gráfico "Sistema" en esa versión de Process Explorer está mal nombrado. Debería estar etiquetado como "commit charge". (En la versión que tengo se llama "Confirmación del sistema". Mejor, pero aún no es completamente consistente.) En cualquier caso, la altura "actual" del gráfico es lo que se muestra en la sección de texto como "Confirmar carga" - " Actual ", y la altura máxima del gráfico representa" Confirmar carga "-" Límite ".

"Confirmar carga" se refiere al espacio de direcciones virtuales respaldado por el archivo de paginación (si tiene uno); en otras palabras, si no cabe todo en la RAM, el resto va en el archivo de paginación. (Hay otros tipos de vas que están respaldados por otros archivos, que se llaman vas "mapeados", o que deben permanecer en la RAM todo el tiempo; este último se llama "no paginable"). El "límite de confirmación" es el máximo que el "cargo de compromiso" puede ser. Es igual al tamaño de su RAM más el tamaño del archivo de paginación.

Aparentemente no tiene un archivo de paginación (puedo decirlo porque su límite de compromiso es igual al tamaño de RAM), por lo que el límite de compromiso es simplemente el tamaño de RAM.

Aparentemente, varios programas + el sistema operativo han utilizado casi todo el máximo compromiso posible.

Esto no tiene nada que ver directamente con la cantidad de RAM disponible o libre. Sí, tiene aproximadamente 4.5 GB de RAM disponibles. Eso no significa que pueda exceder el límite de compromiso. La memoria comprometida no necesariamente usa RAM y no está limitada por la cantidad de RAM disponible.

Debe volver a habilitar el archivo de paginación; con este compromiso, sugeriría un archivo de paginación de 16 GB, porque no desea forzar al sistema operativo a mantener gran parte de esas cosas en la RAM, y el archivo de paginación funciona mejor si tiene mucho espacio libre o agrega más RAM. Mucho más. Para obtener un buen rendimiento, debe tener suficiente espacio en la RAM para el código y otras cosas que no están respaldadas por el archivo de paginación (pero que se pueden paginar a otros archivos).

Respuesta muy larga

(pero aún mucho más corto que el capítulo de administración de memoria de Windows Internals ...)

Supongamos que un programa asigna 100 MB de memoria virtual privada de proceso. Esto se hace con una llamada VirtualAlloc con la opción "commit". Esto dará como resultado un aumento de 100 MB en el "Cargo de compromiso". ¡Pero esta "asignación" en realidad no usa RAM! La RAM solo se usa cuando se accede por primera vez a parte de ese espacio de direcciones virtuales recién comprometido .

Cómo se usa eventualmente la RAM

(si alguna vez lo hace)

El acceso por primera vez al espacio recién comprometido casi siempre sería una escritura en memoria (leer vas privados asignados recientemente antes de escribir es casi siempre un error de programación, ya que sus contenidos iniciales son, estrictamente hablando, indefinidos). Pero leer o escribir, el resultado, la primera vez que toca una página de vas recién asignados, es un error de página . Aunque la palabra "falla" suena mal, las fallas de página son un evento completamente esperado e incluso requerido en un sistema operativo de memoria virtual.

En respuesta a este tipo particular de falla de página, el localizador (parte del administrador de memoria del sistema operativo, que a veces abreviaré como "Mm"):

  1. asignar una página física de RAM (idealmente de la lista de páginas cero, pero en cualquier caso, proviene de lo que Windows llama "disponible": la lista de páginas cero, libre o en espera, en ese orden de preferencia);
  2. complete una entrada de la tabla de páginas para asociar la página física con la página virtual; y finalmente
  3. descartar la excepción de falla de página.

Después de lo cual el código que hizo la referencia de memoria volverá a ejecutar la instrucción que provocó el error de página, y esta vez la referencia tendrá éxito.

Decimos que la página ha sido "introducida" en el conjunto de trabajo del proceso y en la RAM. En el Administrador de tareas, esto aparecerá como un aumento de una página (4 KB) en el "conjunto de trabajo privado" del proceso. Y una reducción de una página en la memoria física disponible. (Esto último puede ser difícil de notar en una máquina ocupada).

Nota 1: este error de página no implicaba nada leído desde el disco. Una página nunca antes accedida de memoria virtual comprometida no comienza la vida en el disco; no tiene lugar en el disco para leerlo desde . Simplemente se "materializa" en una página de RAM previamente disponible. Estadísticamente, de hecho, la mayoría de las fallas de página se resuelven en la RAM, ya sea para páginas compartidas que ya están en RAM para otros procesos, o para las memorias caché de la página, las listas en espera o modificadas, o como páginas "demanda cero" como esta.

Nota 2: Esto toma solo una página, 4096 bytes, de "Disponible". El espacio de direcciones comprometido nunca antes tocado normalmente se realiza, se ingresa de manera errónea, solo una página a la vez, ya que cada página se "toca" por primera vez. No habría ninguna mejora, ninguna ventaja, en hacer más a la vez; solo tomaría n veces más tiempo. Por el contrario, cuando las páginas tienen que leerse desde el disco, se intenta una cierta cantidad de "lectura anticipada" porque la gran mayoría del tiempo en una lectura de disco se realiza por sobrecarga por operación, no la transferencia de datos real. La cantidad "comprometida" se mantiene en 100 MB; El hecho de que una o las páginas hayan sido defectuosas no reduce el cargo de compromiso.

Nota 3:Supongamos que tenemos 4 GB de RAM "disponible". Eso significa que podríamos hacer referencia a la memoria comprometida ya asignada pero nunca antes referenciada aproximadamente un millón de veces más (4 GB / 4096) antes de que nos quedemos sin RAM. En ese momento, si tenemos un archivo de página como David Cutler y Lou Perazzoli pretendían, algunas de las páginas de RAM a las que se hace referencia más tiempo atrás se guardarían en el disco y luego se pondrían a disposición para su uso en la resolución de estas fallas de página más recientes. (En realidad, el sistema operativo iniciaría métodos de recuperación de RAM como "recorte de conjunto de trabajo" antes que eso, y las escrituras reales en el archivo de página se almacenan en caché y se agrupan en la lista de páginas modificadas para mayor eficiencia, y ...) Nada de eso afectaría el recuento "comprometido". Sin embargo, es relevante para el "límite de compromiso". Si no hay espacio para todo "

Y sigue sucediendo ...

Pero supongamos que no hemos hecho esos millones de referencias más y todavía hay alrededor de 4 GB de páginas "disponibles". Ahora supongamos que el mismo proceso, u otro, no importa, hace otro VirtualAlloc, esta vez de 200 MB comprometidos. Nuevamente, estos 200 MB se agregan a la carga de confirmación y no eliminan ninguna RAM disponible. Simplemente el espacio de direcciones VirtualAlloc'ating no usa una cantidad correspondiente de RAM, y tener poca RAM "disponible" no limita la cantidad de espacio de direcciones que puede VirtualAlloc (ni el hecho de tener una RAM alta disponible lo aumenta).

(Bueno, está bien ... hay un poco de sobrecarga, equivalente a una página (¡paginable!) Que se usa para una tabla de páginas por cada 2 MB (4 MB si está en un sistema x86, sin PAE) de espacio de direcciones virtuales asignado, y hay un "descriptor de direcciones virtuales" de unas pocas decenas de bytes para cada rango asignado virtualmente contiguo).

De esta manera es posible, ¡y común! - utilizar una gran cantidad de "carga de compromiso" mientras se usan solo pequeñas cantidades de RAM.

Entonces, si "comprometer" el espacio de direcciones virtuales no usa RAM, ¿por qué tiene que haber un límite?

Porque el "cargo de compromiso" representa el uso potencial futuro del espacio de almacenamiento. El "límite de compromiso" representa la cantidad total de almacenamiento (RAM + espacio de archivo de paginación) disponible para mantener tales asignaciones, en caso de que alguna vez se haga referencia a ellas y, por lo tanto, deban almacenarse en algún lugar.

Cuando el Mm aprueba una solicitud VirtualAlloc, es prometedor, "haciendo un compromiso", que todos los accesos de memoria posteriores al área asignada tendrán éxito; pueden provocar fallas en la página, pero todas las fallas podrán resolverse, ya que hay un almacenamiento adecuado para mantener el contenido de todas esas páginas, ya sea en la RAM o en el archivo de página. El Mm sabe esto porque sabe cuánto espacio de almacenamiento hay (el límite de confirmación) y cuánto ya se ha "comprometido" (el cargo de confirmación actual).

(Pero todavía no se ha accedido necesariamente a todas esas páginas, por lo que no existe necesariamente un almacenamiento real para la cantidad comprometida en un momento dado).

Entonces ... ¿Qué pasa con "el sistema no tiene memoria"?

Si intenta VirtualAlloc y el cargo de confirmación actual más el tamaño de asignación solicitado lo llevarían por encima del límite de confirmación, Y el sistema operativo no puede expandir el archivo de paginación para aumentar el límite de confirmación ... obtendrá el mensaje emergente "sin memoria" arriba, y el proceso ve la llamada VirtualAlloc FAIL. La mayoría de los programas simplemente levantarán sus manos y morirán en ese punto. Algunos presionarán ciegamente, asumiendo que la llamada tuvo éxito, y fallarán más tarde cuando intenten hacer referencia a la región que pensaron que asignaron.

Nuevamente (perdón por la repetición): no importa la cantidad de RAM disponible que tenga. El sistema operativo ha prometido que la RAM o el espacio de archivos de paginación estarán disponibles cuando sea necesario, pero esa promesa no resta de "Disponible". La memoria RAM disponible solo se usa por vm comprometido cuando se hace referencia por primera vez, que es lo que hace que se "produzca una falla" ... es decir, se realiza en la memoria física. Y simplemente confirmar (= asignar) memoria virtual no hace eso. Solo ocupa un espacio de direcciones virtuales gratuito y lo convierte en un espacio de direcciones virtual utilizable.

Pero en el caso de "falta de memoria" ha habido una solicitud de asignación de memoria comprometida, y el sistema operativo ha agregado el cargo de confirmación actual al tamaño de esta nueva solicitud ... y descubrió que el total es mayor que el límite de confirmación. Entonces, si el sistema operativo aprobó este nuevo, y se hizo referencia a todo ese espacio después de eso, no habría ningún lugar real (RAM + archivo de paginación) para almacenarlo todo.

El sistema operativo no permitirá esto. No permitirá que se asigne más vas de los que tiene espacio para mantenerlo en el peor de los casos, incluso si todo se "falla". Ese es el propósito del "límite de compromiso".

Te digo tres veces Te digo tres veces Te digo tres veces: la cantidad de RAM "disponible" no importa. Que el espacio virtual comprometido no esté utilizando todo ese espacio de almacenamiento todavía, no importa. Windows no puede "comprometerse" con la asignación virtual a menos que '' pueda '' fallar en el futuro.

Tenga en cuenta que hay otro tipo de vas llamado "mapeado", utilizado principalmente para el código y para el acceso a archivos de datos de gran tamaño, pero no se carga a "carga de compromiso" y no está limitado por el "límite de compromiso". Esto se debe a que viene con su propia área de almacenamiento, los archivos que están "asignados" a ella. El único límite en el vas "mapeado" es la cantidad de espacio en disco que tiene para los archivos mapeados y la cantidad de vas libre en su proceso para mapearlos.

Pero cuando miro el sistema, ¿todavía no estoy en el límite de confirmación?

Eso es básicamente un problema de medición y mantenimiento de registros. Está mirando el sistema después de que una llamada VirtualAlloc ya se haya intentado y haya fallado.

Supongamos que le quedaban solo 500 MB de límite de confirmación y algún programa había intentado VirtualAlloc 600 MB. El intento falla. Luego miras el sistema y dices "¿Qué? ¡Todavía quedan 500 MB!" De hecho, podría haber muchísimo más para entonces, porque el proceso en cuestión probablemente haya desaparecido por completo en ese punto, por lo que TODA su memoria comprometida previamente asignada se ha liberado.

El problema es que no se puede mirar hacia atrás en el tiempo y ver lo que el cometer cargo fue en este momento se hizo el intento alloc. Y tampoco sabes para cuánto espacio fue el intento. Por lo tanto, no puede ver definitivamente por qué falló el intento, o cuánto más se habría necesitado "límite de compromiso" para permitir que funcione.

He visto "el sistema se está quedando sin memoria". ¿Que es eso?

Si en el caso anterior, el SO PUEDE expandir el archivo de paginación (es decir, lo deja en la configuración predeterminada "administrado por el sistema", o lo administra pero establece el máximo en más grande que el inicial, Y hay suficiente espacio libre en el disco), y dicha expansión aumenta el límite de confirmación lo suficiente como para permitir que la llamada VirtualAlloc tenga éxito, entonces ... el Mm expande el archivo de paginación y la llamada VirtualAlloc tiene éxito.

Y ahí es cuando ves "el sistema se ejecuta BAJO en la memoria". Esa es una advertencia temprana de que si las cosas continúan sin mitigación, es probable que pronto vea una advertencia de "falta de memoria". Es hora de cerrar algunas aplicaciones. Comenzaría con las ventanas de tu navegador.

¿Y crees que es algo bueno? ¡La expansión del archivo de paginación es malvada!

No lo es. Verá, el sistema operativo realmente no "expande" el archivo existente. Simplemente asigna una nueva extensión. El efecto es muy similar a cualquier otro archivo no contiguo. El contenido antiguo del archivo de paginación permanece donde está; no tienen que ser copiados a un lugar nuevo ni nada por el estilo. Dado que la mayoría de las E / S de archivos de paginación se encuentran en fragmentos relativamente pequeños en comparación con el tamaño del archivo de paginación, las posibilidades de que una transferencia dada cruce un límite de extensión son realmente bastante raras, por lo que la fragmentación no duele mucho a menos que sea realmente excesiva.

Finalmente, una vez que todos los procesos que tienen espacio "comprometido" en la extensión se han cerrado (en el cierre del sistema operativo, si no antes), las extensiones se liberan silenciosamente y el archivo de paginación volverá a su tamaño y asignación anteriores, si antes era contiguo, Es así de nuevo.

Por lo tanto, permitir la expansión del archivo de paginación actúa como una red de seguridad completamente gratuita: si lo permite pero el sistema nunca lo necesita, el sistema no "expandirá y contraerá constantemente el archivo de paginación" como se afirma a menudo, por lo que no costará nada . Y si alguna vez lo necesita, lo salvará de las aplicaciones que se bloquean con errores de "memoria virtual insuficiente".

Pero pero pero...

He leído en docenas de sitios web que si permite la expansión del archivo de página, Windows se expandirá y contraerá constantemente, y que esto provocará la fragmentación del archivo de página hasta que lo desfragmente.

Simplemente están equivocados.

Si nunca ha visto la ventana emergente "con poca memoria" (o, en versiones anteriores, "poca memoria virtual"), el sistema operativo nunca ha expandido su archivo de paginación.

Si ve esa ventana emergente, eso le indica que el tamaño inicial de su archivo de página es demasiado pequeño. (Me gusta establecerlo en aproximadamente 4 veces el uso máximo observado; es decir, el contador de rendimiento "% de uso máximo del archivo de página" debe ser inferior al 25%. Motivo: El espacio del archivo de página se administra como cualquier otro montón y funciona mejor con mucho espacio libre para jugar)

Pero por qué no solo ...

Uno podría argumentar que el sistema operativo debería permitir que la asignación suceda y luego dejar que las referencias fallen si no hay RAM disponible para resolver las fallas de la página. En otras palabras, arriba, donde describimos cómo funciona la falla de la página inicial, ¿qué sucede si no se puede "asignar una página física de RAM disponible" (paso 1) porque no había ninguna disponible y no había lugar? izquierda para buscar algo para poner a disposición?

Entonces el localizador no podría resolver la falla de la página. Tendría que permitir que la excepción (la falla de la página) sea informada nuevamente al hilo que falla, probablemente cambiado a algún otro código de excepción.

La filosofía de diseño es que VirtualAlloc devolverá cero (técnicamente un puntero NULO) en lugar de una dirección si se agota el límite de confirmación, y es completamente razonable esperar que el programador sepa que una llamada de VirtualAlloc puede fallar. Por lo tanto, se espera que los programadores verifiquen ese caso y hagan algo razonable en respuesta (como darle la oportunidad de guardar su trabajo hasta ese punto y luego finalizar el programa "con gracia"). (Programadores: Verifica si hay un retorno de puntero NULL de malloc, nuevo, etc., ¿sí? ¿Entonces por qué no lo harías?)

Pero los programadores no deberían esperar que una simple referencia de memoria como

i = 0;             // initialize loop counter

podría fallar, no si está en una región de espacio de direcciones comprometido con éxito. (O espacio de direcciones mapeado, para el caso). Pero eso es lo que podría suceder si se siguiera la filosofía "permitir la asignación excesiva, dejar que la referencia de memoria falle".

¡Desafortunadamente, una referencia de memoria como la de la línea de código anterior simplemente no tiene una forma conveniente de devolver un mal estado! Se supone que solo funcionan , como sumar y restar. La única forma de reportar tales fallas sería como excepciones. Entonces, para manejarlos, el programador tendría que envolver todo el programa en un controlador de excepciones. (intente ... atrapar y todo eso)

Eso se puede hacer ... Pero sería difícil para el controlador saber cómo "hacer lo correcto" en respuesta a esas excepciones, ya que habría muchos, muchos puntos en el código donde podrían surgir. (Específicamente, podrían surgir en cada referencia de memoria a la memoria VirtualAlloc'd, a la memoria asignada con malloc o new ... y a todas las variables locales también, ya que la pila también es VirtualAlloc'd).

En resumen, hacer que el programa falle con gracia en estos casos sería muy difícil.

Es bastante fácil, por otro lado, verificar si hay un puntero NULL devuelto por VirtualAlloc (o malloc o nuevo, aunque no son exactamente lo mismo) y luego hacer algo razonable ... como no intentar ir y hacer lo que sea que el programa necesitaba ese espacio virtual. Y tal vez pregunte al usuario si desea guardar su trabajo hasta ahora, si corresponde. (De acuerdo, demasiadas aplicaciones no se molestan en hacer incluso eso).

Otros usuarios de commit

Por cierto, el "límite de compromiso" no se reduce por las diversas asignaciones del sistema operativo, como el grupo paginado y no paginado, la lista PFN, etc. estos solo son acusados ​​de cometer cargos a medida que ocurren. Tampoco la carga de compromiso o el límite de compromiso se ven afectados por la RAM de video, ni tampoco el tamaño de la "ventana" de RAM de video.

Pruébelo usted mismo

Puede hacer una demostración de todo esto con la herramienta testlimit del sitio SysInternals. La opción -m asignará el espacio de direcciones comprometido pero no lo "tocará", por lo que no causará la asignación de RAM. Mientras que la opción -d asignará y también hará referencia a las páginas, lo que hará que tanto la carga de confirmación aumente como que disminuya la RAM disponible.

Referencias

Windows Internals por Russinovich, Solomon e Ionescu. Incluso hay demostraciones que le permiten probar todos estos puntos utilizando la herramienta testlimit. Sin embargo, debo advertirte que si crees que esto fue largo, ten cuidado: el capítulo Mm solo tiene 200 páginas; Lo anterior es una versión EXTREMADAMENTE simplificada. (Consulte también la sección "Agradecimientos" en la Introducción).

Consulte también la documentación de MSDN VirtualAlloc

Jamie Hanrahan
fuente
44
@AcePL Le expliqué por qué. En pocas palabras: está sucediendo porque su límite de confirmación es demasiado bajo para su carga de trabajo. El límite de confirmación es el tamaño total de RAM + el tamaño actual del archivo de paginación. La cantidad de RAM "disponible" no entra en él. El mecanismo de "límite de compromiso" no permitirá la asignación de espacio de direcciones virtuales más allá de la disponibilidad de almacenamiento físico (RAM + almacén de respaldo en el disco, es decir, archivo de paginación) para mantener el material. Recuerde, a pesar de que es virtual, debe guardarse en algún lugar una vez que se ha introducido por primera vez.
Jamie Hanrahan
55
@AcePL: el usuario no se está quedando sin memoria. Se está quedando sin memoria virtual. Esta explicación es 100% válida.
Ramhound
1
@Rahul Basu En realidad, esperaría que el breve comentario fuera mucho más difícil de entender. ;) Esta y muchas preguntas similares son evidencia de que muchas personas tienen algunas ideas falsas sobre la memoria virtual, los espacios de direcciones, los conjuntos de trabajo, etc. No es su culpa: es un tema muy complejo y las pantallas de MS nunca han sido tan claras como podrían ser. . Pero se necesitan muchas palabras para explicar incluso una parte. El Windows Internals tiene esquemas que facilitan. Los diagramas animados serían aún mejores ...
Jamie Hanrahan
3
Posiblemente de interés: "simplemente deje que ocurra la asignación y luego deje que las referencias fallen si no hay RAM disponible para resolver las fallas de la página" es similar a lo que Linux hace de manera predeterminada: permite una cierta cantidad de sobrecompromiso, pero en algún momento " Se quedará sin memoria virtual para páginas sucias y es entonces cuando el asesino sin memoria entra en acción ... y mata lo que podría ser un proceso completamente no relacionado . Si, desagradable.
Bob
1
@JamieHanrahan Parece que ya lo hiciste (lo siento, estaba un poco ocupado). Sí, overcommit es configurable, y algunas distribuciones lo deshabilitarán. Pero parece que todavía era común en 2013 y 2014 , y creo que es el valor predeterminado del núcleo cuando no se establece explícitamente (por distribución o por usuario).
Bob