GNU/Linux >> Tutoriales Linux >  >> Linux

¿Linux realiza intercambios oportunistas o es un mito?

Linux no realiza "intercambios oportunistas" como se define en esta pregunta.

Las siguientes referencias principales no mencionan el concepto en absoluto:

  1. Comprensión del administrador de memoria virtual de Linux. Un libro en línea de Mel Gorman. Escrito en 2003, justo antes del lanzamiento de Linux 2.6.0.
  2. Documentación/admin-guide/sysctl/vm.rst. Esta es la documentación principal de la configuración ajustable de la administración de memoria virtual de Linux.

Más específicamente:

10.6 Demonio de salida de página (kswapd)

Históricamente kswapd Solía ​​activarse cada 10 segundos, pero ahora solo lo activa el asignador de páginas físicas cuando se alcanza el número de páginas libres en una zona. [...] Bajo una presión de memoria extrema, los procesos harán el trabajo de kswapd sincrónicamente [...] kswapd continúa liberando páginas hasta que se alcanza la marca de agua pages_high.

Según lo anterior, no esperaríamos ningún intercambio cuando el número de páginas gratuitas sea mayor que la "marca de agua máxima".

En segundo lugar, esto nos dice el propósito de kswapd es hacer más páginas gratuitas.

Cuando kswapd escribe una página de memoria para intercambiar, inmediatamente libera la página de memoria. kswapd no guarda una copia de la página intercambiada en la memoria .

Linux 2.6 usa el "rmap" para liberar la página. En Linux 2.4, la historia era más compleja. Cuando varios procesos compartían una página, kswapd no podía liberarla inmediatamente. Esta es la historia antigua. Todas las publicaciones vinculadas son sobre Linux 2.6 o superior.

intercambio

Este control se utiliza para definir la agresividad con la que el kernel intercambiará páginas de memoria. Los valores más altos aumentarán la agresividad, los valores más bajos disminuirán la cantidad de intercambio. Un valor de 0 le indica al kernel que no inicie el intercambio hasta que se agote la cantidad de páginas libres y respaldadas por archivos. es menor que la marca de agua alta en una zona.

Esta cita describe un caso especial:si configura el swappiness valor para ser 0 . En este caso, tampoco deberíamos esperar ningún intercambio hasta que el número de páginas de caché haya caído al límite máximo. En otras palabras, el kernel intentará descartar casi todo el caché de archivos antes de comenzar a intercambiar. (Esto podría causar ralentizaciones masivas. ¡Necesita tener un caché de archivos! El caché de archivos se utiliza para almacenar el código de todos sus programas en ejecución :-)

¿Qué son las marcas de agua?

Las citas anteriores plantean la pregunta:¿Qué tan grandes son las reservas de memoria de "marca de agua" en mi sistema? Respuesta:en un sistema "pequeño", las marcas de agua de zona predeterminadas pueden llegar al 3% de la memoria. Esto se debe al cálculo de la marca de agua "mín". En sistemas más grandes, las marcas de agua serán una proporción más pequeña, acercándose al 0,3 % de la memoria.

Entonces, si la pregunta es sobre un sistema con más del 10 % de memoria libre, los detalles exactos de esta lógica de marca de agua no son significativos.

Las marcas de agua para cada "zona" individual se muestran en /proc/zoneinfo , como se documenta en proc(5). Un extracto de mi zoneinfo:

Node 0, zone    DMA32
  pages free     304988
        min      7250
        low      9062
        high     10874
        spanned  1044480
        present  888973
        managed  872457
        protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone   Normal
  pages free     11977
        min      9611
        low      12013
        high     14415
        spanned  1173504
        present  1173504
        managed  1134236
        protection: (0, 0, 0, 0, 0)

Las "marcas de agua" actuales son min , low y high . Si un programa alguna vez solicita suficiente memoria para reducir free debajo de min , el programa entra en "reclamación directa". El programa está hecho para esperar mientras el kernel libera memoria.

Queremos evitar la reclamación directa si es posible. Así que si free caería por debajo del low marca de agua, el núcleo activa kswapd . kswapd libera memoria intercambiando y/o eliminando cachés, hasta free está por encima de high de nuevo.

Cualificación adicional:kswapd también se ejecutará para proteger la cantidad completa de lowmem_reserve, para el uso de kernel lowmem y DMA. El lowmem_reserve predeterminado es aproximadamente 1/256 de los primeros 4 GiB de RAM (zona DMA32), por lo que suele rondar los 16 MiB.

Confirmaciones de código Linux

mm:escala kswapd marcas de agua en proporción a la memoria

[...]

marca_de_agua_factor_de_escala:

Este factor controla la agresividad de kswapd. Define la cantidad de memoria que queda en un nodo/sistema antes de que kswapd se despierte y cuánta memoria debe estar libre antes de que kswapd vuelva a dormir.

La unidad está en fracciones de 10.000. El valor predeterminado de 10 significa que las distancias entre las marcas de agua son el 0,1 % de la memoria disponible en el nodo/sistema. El valor máximo es 1000, o el 10 % de la memoria.

Una alta tasa de subprocesos que ingresan a la reclamación directa (allocstall) o que kswapd se va a dormir prematuramente (kswapd_low_wmark_hit_quickly) puede indicar que la cantidad de páginas libres que kswapd mantiene por razones de latencia es demasiado pequeña para las ráfagas de asignación que ocurren en el sistema. Esta perilla se puede usar para ajustar la agresividad de kswapd en consecuencia.

proc:meminfo:calcule la memoria disponible de forma más conservadora

El MemAvailable artículo en /proc/meminfo es dar a los usuarios una pista de cuánta memoria se puede asignar sin causar un intercambio, por lo que excluye las marcas de agua bajas de las zonas como no disponibles para el espacio del usuario.

Sin embargo, para una asignación de espacio de usuario, kswapd en realidad reclamará hasta que las páginas gratuitas alcancen una combinación de la marca de agua alta y la protección de memoria baja del asignador de páginas que también mantiene una cierta cantidad de memoria DMA y DMA32 del espacio del usuario.

Resta la cantidad total que sabemos que no está disponible para el espacio de usuario de la cantidad de páginas libres al calcular MemAvailable.

Código Linux

A veces se afirma que cambiar swappiness a 0 deshabilitará efectivamente el "intercambio oportunista". Esto proporciona una interesante vía de investigación. Si hay algo llamado "intercambio oportunista", y se puede ajustar mediante swappiness, entonces podríamos perseguirlo encontrando todas las cadenas de llamadas que dicen vm_swappiness . Tenga en cuenta que podemos reducir nuestro espacio de búsqueda asumiendo CONFIG_MEMCG no está configurado (es decir, los "cgroups de memoria" están deshabilitados). La cadena de llamadas va:

  • vm_swappiness
  • mem_cgroup_swappiness
  • get_scan_count
  • shrink_node_memcg
  • shrink_nodo

shrink_node_memcg se comenta "Esta es una página básica por nodo más libre. Utilizada tanto por kswapd como por reclamo directo". Es decir. esta función aumenta el número de gratis paginas No está tratando de duplicar páginas para intercambiar para que puedan liberarse mucho más tarde. Pero incluso si descontamos eso:

La cadena anterior se llama desde tres funciones diferentes, que se muestran a continuación. Como era de esperar, podemos dividir los sitios de llamada en reclamo directo vs. kswapd. No tendría sentido realizar un "intercambio oportunista" en la recuperación directa.

  1. /*
     * This is the direct reclaim path, for page-allocating processes.  We only
     * try to reclaim pages from zones which will satisfy the caller's allocation
     * request.
     *
     * If a zone is deemed to be full of pinned pages then just give it a light
     * scan then give up on it.
     */
    static void shrink_zones
    
  2.  * kswapd shrinks a node of pages that are at or below the highest usable
     * zone that is currently unbalanced.
     *
     * Returns true if kswapd scanned at least the requested number of pages to
     * reclaim or if the lack of progress was due to pages under writeback.
     * This is used to determine if the scanning priority needs to be raised.
     */
    static bool kswapd_shrink_node
    
  3.  * For kswapd, balance_pgdat() will reclaim pages across a node from zones
     * that are eligible for use by the caller until at least one zone is
     * balanced.
     *
     * Returns the order kswapd finished reclaiming at.
     *
     * kswapd scans the zones in the highmem->normal->dma direction.  It skips
     * zones which have free_pages > high_wmark_pages(zone), but once a zone is
     * found to have free_pages <= high_wmark_pages(zone), any page in that zone
     * or lower is eligible for reclaim until at least one usable zone is
     * balanced.
     */
    static int balance_pgdat
    

Entonces, presumiblemente, la afirmación es que kswapd se activa de alguna manera, incluso cuando todas las asignaciones de memoria se satisfacen inmediatamente desde la memoria libre. Revisé los usos de wake_up_interruptible(&pgdat->kswapd_wait) , y no veo ningún despertar como este.


No, no existe el intercambio oportunista en Linux. Pasé un tiempo analizando el problema y todas las fuentes (libros de texto, correos electrónicos en las listas de correo de los desarrolladores del kernel, código fuente de Linux y comentarios de confirmación, y algunos intercambios de Twitter con Mel Gorman) me dicen lo mismo:Linux solo reclama memoria en respuesta a alguna forma de presión de la memoria (con la obvia excepción de la hibernación).

Todos los conceptos erróneos populares sobre el tema probablemente se derivan del simple hecho de que Linux no puede darse el lujo de esperar hasta el último byte de memoria libre antes de comenzar el intercambio. Necesita algún tipo de colchón para protegerlo de formas extremas de agotamiento de la memoria, y hay algunos ajustes que pueden afectar el tamaño de ese colchón (por ejemplo, vm.min_free_kbytes ). Pero no es lo mismo que "cambiar porque no hay nada mejor que hacer".

Desafortunadamente, el algoritmo de recuperación de marcos de página se ha vuelto mucho más complejo con respecto a 2.6 (cuando se describió en detalle en el libro de Mel Gorman), pero la idea básica es más o menos la misma:la recuperación de página se desencadena por asignaciones fallidas, que luego despierta kswapd o intente liberar páginas sincrónicamente (según la presión de la memoria, los indicadores de asignación y otros factores).

La razón más obvia por la que las asignaciones de páginas pueden comenzar a fallar con suficiente memoria libre es que pueden estar solicitando memoria contigua cuando en realidad la memoria puede estar demasiado fragmentada para satisfacer la solicitud. Históricamente, los desarrolladores del kernel de Linux hicieron todo lo posible para evitar la necesidad de asignaciones contiguas. Sin embargo, algunos controladores de dispositivos todavía requieren eso, ya sea porque no pueden hacer E/S de memoria de varias páginas (DMA de dispersión y recopilación), o porque los desarrolladores de controladores pueden codificar de manera descuidada. La llegada de Transparent Huge Pages (THP) proporcionó otra razón para asignar memoria en fragmentos físicamente contiguos.

Se supone que la compactación de zonas, que se introdujo aproximadamente al mismo tiempo, ayuda con el problema de fragmentación de la memoria, pero no siempre produce el efecto esperado.

Hay varios vmscan puntos de rastreo que pueden ayudar a comprender qué está pasando exactamente en su caso específico:siempre es más fácil encontrar lo que necesita en el código del kernel de Linux cuando tiene pilas de llamadas específicas, en lugar de simplemente escanear todo lo que parece remotamente relevante.


Linux
  1. Linux:¿Linux realiza un "intercambio oportunista" o es un Theth?

  2. Linux gratis muestra un alto uso de memoria pero la parte superior no

  3. ¿Cómo funciona la asignación de pila en Linux?

  4. Memoria inactiva de Linux

  5. ¿Qué asesinos de procesos tiene Linux?

Cómo borrar la memoria de intercambio en Linux

¿Cómo funciona el intercambio de memoria en Linux?

Ejemplos de comandos gratuitos en Linux

¿La asignación de memoria en Linux no bloquea?

Segmentación de memoria de Linux

¿Linux puede limpiar la memoria?