¿Hay alguna manera de detectar la fragmentación de la memoria en Linux? Esto se debe a que en algunos servidores de larga ejecución he notado una degradación del rendimiento y solo después de reiniciar el proceso veo un mejor rendimiento. Lo noté más cuando uso el soporte de páginas enormes de Linux: ¿son las páginas enormes de Linux más propensas a la fragmentación?
He mirado / proc / buddyinfo en particular. Quiero saber si hay mejores formas (no solo los comandos CLI per se, cualquier programa o antecedentes teóricos lo harían) para verlo.
linux
linux-kernel
Raghu
fuente
fuente
vmstat
en el camposo
?vmstat
es una experiencia de usuario común. Si estuviera escribiendo un programa para hacer lo mismo, sería diferente. Si tiene la intención de usar bash para cosechar esta información, edite su pregunta, no se cerrará :)Respuestas:
Estoy respondiendo a la etiqueta de Linux . Mi respuesta es específica solo para Linux .
Sí, las páginas enormes son más propensas a la fragmentación. Hay dos vistas de memoria, la que obtiene su proceso (virtual) y la que administra el núcleo (real). Cuanto más grande sea una página, más difícil será agrupar (y mantener con) sus vecinos, especialmente cuando su servicio se ejecuta en un sistema que también tiene que admitir otros que, por defecto, asignan y escriben más memoria de la que ellos tienen. en realidad terminan usando.
La asignación del núcleo de direcciones (reales) otorgadas es privada. Hay una muy buena razón por la cual el espacio de usuario los ve como el núcleo los presenta, porque el núcleo debe poder comprometerse en exceso sin confundir el espacio de usuarios. Su proceso obtiene un espacio de direcciones "Disneyfied" agradable y contiguo en el que trabajar, ajeno a lo que el núcleo está haciendo realmente con esa memoria detrás de escena.
La razón por la que se ve el rendimiento sea menor en los servidores de larga ejecución es más probable porque los bloques asignados que no han sido bloqueados de forma explícita (por ejemplo
mlock()
/mlockall()
oposix_madvise()
) y no modificada desde hace tiempo se han paginado , lo que significa que sus patines de servicios en el disco cuando se tiene que leer ellos. La modificación de este comportamiento hace que su proceso sea un mal vecino , por lo que muchas personas colocan su RDBMS en un servidor completamente diferente a web / php / python / ruby / lo que sea. La única forma de arreglar eso, sensatamente, es reducir la competencia por los bloques contiguos.La fragmentación solo es realmente notable (en la mayoría de los casos) cuando la página A está en la memoria y la página B se ha movido para intercambiar. Naturalmente, reiniciar su servicio parecería "curar" esto, pero solo porque el núcleo aún no ha tenido la oportunidad de distribuir el proceso "(ahora) bloques recientemente asignados dentro de los límites de su relación de sobrecompromiso.
De hecho, reiniciar (digamos) 'apache' bajo una carga alta probablemente enviará bloques propiedad de otros servicios directamente al disco. Entonces, sí, 'apache' mejoraría por un corto tiempo, pero 'mysql' podría sufrir ... al menos hasta que el núcleo los haga sufrir por igual cuando simplemente hay una falta de memoria física suficiente.
Agregue más memoria o divida a los
malloc()
consumidores exigentes :) No es solo la fragmentación lo que debe estar observando.Intenta
vmstat
obtener una visión general de lo que realmente se está almacenando y dónde.fuente
Núcleo
Para obtener el índice de fragmentación actual, use:
Para desfragmentar la memoria del núcleo, intente ejecutar:
También intente desactivar Transparent Huge Pages (también conocido como THP) y / o deshabilitar el intercambio (o disminuir
swappiness
).Espacio de usuario
Para reducir la fragmentación del espacio de usuario, es posible que desee probar un asignador diferente, por ejemplo
jemalloc
(tiene excelentes capacidades de introspección , lo que le dará una fragmentación interna del asignador).Puede cambiar a malloc personalizado volviendo a compilar su programa con él o simplemente ejecutando su programa con
LD_PRELOAD
:LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app
(tenga cuidado con las interacciones entre THP y los asignadores de memoria )Aunque, ligeramente no relacionado con la fragmentación de la memoria (pero conectado a la compactación / migración de la memoria), probablemente desee ejecutar varias instancias de su servicio, una para cada nodo NUMA y vincularlas usando
numactl
.fuente
mmap
) se implementan de manera diferente en diferentes núcleos (por ejemplo, Linux vs FreeBSD), o incluso en diferentes versiones del mismo sistema operativo (2.6.32 vs 3.2 vs 3.10) ... "permite páginas modificadas [. ..] para ser expulsado de la [...] memoria física ", eso ocultará las pérdidas de memoria. "manejar casos en los que se reserva mucha más memoria de la utilizada": el sistema lento es mucho peor que el sistema inactivo, por lo que "cuerdo" es cuestionable.El uso de páginas enormes no debería causar fragmentación de memoria adicional en Linux; El soporte de Linux para páginas grandes es solo para memoria compartida (a través de shmget o mmap), y cualquier página grande utilizada debe ser solicitada específicamente y previamente asignada por un administrador del sistema. Una vez en la memoria, se fijan allí y no se intercambian. El desafío de intercambiar páginas enormes frente a la fragmentación de la memoria es exactamente por qué permanecen ancladas en la memoria (al asignar una página enorme de 2 MB, el núcleo debe encontrar 512 páginas contiguas libres de 4KB, que incluso pueden no existir).
Documentación de Linux en páginas enormes: http://lwn.net/Articles/375098/
Hay una circunstancia en la que la fragmentación de la memoria podría hacer que la asignación de páginas grandes sea lenta (pero no donde las páginas grandes causen la fragmentación de la memoria), y eso es si su sistema está configurado para aumentar el grupo de páginas enormes si lo solicita una aplicación. Si / proc / sys / vm / nr_overcommit_hugepages es mayor que / proc / sys / vm / nr_hugepages, esto podría suceder.
fuente
Hay
/proc/buddyinfo
que es muy útil. Es más útil con un buen formato de salida, como este script Python puede hacer:https://gist.github.com/labeneator/9574294
Para páginas grandes, desea algunos fragmentos libres en el tamaño 2097152 (2MiB) o más grande. Para páginas grandes transparentes, se compactará automáticamente cuando se le pida al kernel, pero si desea ver cuántas puede obtener, entonces, como raíz, ejecute:
También sí, las páginas enormes causan grandes problemas de fragmentación. O no puede obtener páginas grandes, o su presencia hace que el núcleo pase mucho tiempo extra tratando de obtener algunas.
Tengo una solución que me funciona. Lo uso en un par de servidores y mi computadora portátil. Funciona muy bien para máquinas virtuales.
Agregue la
kernelcore=4G
opción a su línea de comando del kernel de Linux. En mi servidor uso 8G. Tenga cuidado con el número, porque evitará que su núcleo asigne cualquier cosa fuera de esa memoria. A los servidores que necesitan una gran cantidad de buffers de socket o que transmiten escrituras en disco a cientos de unidades no les gustará estar limitados de esta manera. Cualquier asignación de memoria que deba "anclarse" para losa o DMA está en esta categoría.Toda la otra memoria se convierte en "móvil", lo que significa que se puede compactar en trozos agradables para una gran asignación de páginas. Ahora las grandes páginas transparentes realmente pueden despegar y funcionar como se supone que deben hacerlo. Cada vez que el núcleo necesita más páginas de 2M, simplemente puede reasignar páginas de 4K a otro lugar.
Y no estoy totalmente seguro de cómo interactúa esto con la E / S directa de copia cero. Se supone que la memoria en la "zona móvil" no está anclada, pero una solicitud directa de E / S haría exactamente eso para DMA. Podría copiarlo. De todos modos, podría fijarlo en la zona móvil. En cualquier caso, probablemente no sea exactamente lo que querías.
fuente