¿Por qué las discusiones sobre "swappiness" actúan como si la información solo pudiera estar en un lugar a la vez?

StackOverflow https://stackoverflow.com/questions/147125

Pregunta

He estado leyendo sobre la "swappiness" de Linux optimizable, que controla qué tan agresivo es el kernel para cambiar la memoria de las aplicaciones al disco cuando no se están utilizando. Si buscas el término en Google, obtienes muchas páginas como this discutir los pros y los contras. En pocas palabras, el argumento es el siguiente:

  

Si su velocidad es demasiado baja, las aplicaciones inactivas ocuparán toda la memoria del sistema que otros programas podrían querer usar.

     

Si su rapidez es demasiado alta, cuando despierte esas aplicaciones inactivas, habrá una gran demora a medida que su estado se recupere del disco.

Este argumento no tiene sentido para mí. Si tengo una aplicación inactiva que usa una tonelada de memoria, ¿por qué el núcleo no coloca su memoria en el disco Y deja otra copia de esos datos en la memoria? Esto parece dar lo mejor de ambos mundos: si otra aplicación necesita esa memoria, puede reclamar inmediatamente la memoria RAM física y comenzar a escribir en ella, ya que otra copia de ella está en el disco y puede volver a intercambiarse cuando se activa la aplicación inactiva arriba. Y cuando la aplicación original se activa, cualquiera de sus páginas que aún se encuentran en la memoria RAM se puede usar como está, sin tener que sacarla del disco.

¿O me falta algo?

¿Fue útil?

Solución

De acuerdo con este 1 que es exactamente lo que Linux lo hace.

Todavía estoy tratando de darle sentido a mucho de esto, por lo que cualquier enlace autorizado sería apreciado.

Otros consejos

  

Si tengo una aplicación inactiva que usa una tonelada de memoria, ¿por qué el kernel no coloca su memoria en el disco Y deja otra copia de esos datos en la memoria?

Digamos que lo hicimos. Escribimos la página en el disco, pero la dejamos en la memoria. Poco después, otro proceso necesita memoria, por lo que queremos sacar la página del primer proceso.

Necesitamos saber con absoluta certeza si el primer proceso ha modificado la página desde que se escribió en el disco. Si es así, tenemos que escribirlo de nuevo. La forma en que rastrearíamos esto es quitar el permiso de escritura del proceso a la página cuando la escribimos por primera vez en el disco. Si el proceso intenta volver a escribir en la página, habrá un error de página. El núcleo puede observar que el proceso ha ensuciado la página (y, por lo tanto, deberá escribirse nuevamente) antes de restaurar el permiso de escritura y permitir que la aplicación continúe.

Ahí radica el problema. Retirar el permiso de escritura de la página es en realidad algo costoso, particularmente en máquinas multiprocesador. Es importante que todas las CPU eliminen el caché de las traducciones de la página para asegurarse de que quitan el permiso de escritura.

Si el proceso escribe en la página, tomar un error de página es aún más costoso. Supongo que un número no trivial de estas páginas terminaría tomando esa falla, lo que se traduce en las ganancias que buscábamos al dejarlo en la memoria.

Entonces, ¿vale la pena hacerlo? Sinceramente no lo sé. Solo estoy tratando de explicar por qué dejar la página en la memoria no es una ganancia tan obvia como parece.

(*) Todo esto es muy similar a un mecanismo llamado Copy-On-Write, que se usa cuando un fork de proceso () s. Es muy probable que el proceso hijo solo ejecute unas pocas instrucciones y llame a exec (), por lo que sería una tontería copiar todas las páginas de los padres. En su lugar, el permiso de escritura se retira y el niño simplemente se deja correr. Copy-On-Write es una ganancia porque la falla de la página casi nunca se toma: el niño casi siempre llama a exec () inmediatamente.

Incluso si coloca la memoria de las aplicaciones en el disco y la guarda en la memoria, aún tendría que decidir cuándo debe considerarse una aplicación " inactiva " y eso es lo que controla el swapiness. La paginación al disco es costosa en términos de IO y no desea hacerlo con demasiada frecuencia. También hay otra variable en esta ecuación, y ese es el hecho de que Linux utiliza la memoria restante como buffers de disco / caché.

Lo primero que hace la máquina virtual es limpiar las páginas y moverlas a la lista de limpieza.
Al limpiar la memoria anónima (las cosas que no tienen un almacén de respaldo de archivos real, puede ver los segmentos en / proc // mapas que son anónimos y no tienen almacenamiento de vnodo de sistema de archivos detrás de ellos), lo primero que hará la VM es tomar el " sucio " páginas y " limpio " luego escribiendo el contenido de la página para intercambiar. Ahora, cuando la VM tiene una escasez de memoria completamente libre y está preocupada por su capacidad de otorgar nuevas páginas gratuitas para ser utilizadas, puede revisar la lista de páginas "limpias" y basarse en la forma en que se usaron recientemente y el tipo de memoria. son las que moverán esas páginas a la lista gratuita.

Una vez que las páginas de memoria se colocan en la lista libre, ya no están asociadas con el contenido que tenían antes. Si un programa se presenta junto con una referencia a la ubicación de la memoria en la que se encontraba la página anteriormente, el programa tendrá una falla mayor y se tomará una página (probablemente completamente diferente) de la lista gratuita y los datos se leerán en la página desde el disco. Una vez hecho esto, la página todavía está "limpia", ya que no se ha modificado. Si la máquina virtual elige usar esa página en el intercambio por una página diferente en la RAM, la página volverá a estar "sucia", o si la aplicación escribió en esa página, estaría "sucia". Y luego el proceso comienza de nuevo.

Además, Swappinness es bastante horrible para las aplicaciones de servidor en un entorno empresarial / transaccional / en línea / sensible a la latencia. Cuando tengo cajas de memoria RAM de 16 GB en las que no ejecuto muchos navegadores e interfaces de usuario (GUI), normalmente quiero que todas mis aplicaciones estén casi guardadas en la memoria. La mayor parte de mi RAM tiende a ser de 8-10GB java montones que NUNCA quiero paginados al disco, y el cruft que está disponible es un proceso como mingetty (pero incluso allí están las páginas glibc en esas aplicaciones son compartidos por otras aplicaciones y se utilizan realmente, por lo que incluso el tamaño RSS de esos procesos inútiles se comparten en su mayoría, las páginas utilizadas). Normalmente no veo más de unos 10 MB de los 16 GB que se han limpiado para intercambiar. Recomendaría números muy, muy bajos de swappiness o cero swappiness para los servidores: las páginas no utilizadas deberían ser una pequeña fracción de la RAM general y tratar de reclamar esa cantidad relativamente pequeña de RAM para el caché de búfer corre el riesgo de intercambiar las páginas de aplicaciones y tomar los resultados de latencia la aplicación en ejecución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top