Linux NUMA Las estadísticas me muestran en qué medida los procesos conservan su memoria de forma local y dónde los accesos remotos aumentan la latencia. Explico cómo interpreto estas cifras de forma específica, evalúo las tendencias a lo largo del tiempo y, a partir de ahí, defino medidas claras de optimización para Actuación derivar.
Puntos centrales
- Entender los contadores: numa_hit, numa_miss, numa_foreign, local_node, other_node, interleave_hit
- Evaluar el contexto: Perfil de carga, topología, tipo de carga de trabajo
- Medir las tendencias: Antes/después y por intervalos
- Comprobar los procesos: A nivel de todo el sistema frente a por proceso
- Aplicar ajustes: Afinidad, políticas, ubicación
Lo que realmente muestran las estadísticas NUMA
Interpreto las cifras de NUMA como un mapa de Almacén y vías de transmisión de datos. Un alto numa_hit significa que las asignaciones se han realizado en el nodo deseado. Por el contrario, «numa_miss» indica que el núcleo ha tenido que recurrir a otro nodo. El contador «numa_foreign» muestra el equivalente en el nodo de destino y completa el panorama. Con local_node y other_node puedo saber si los accesos se han realizado de forma local o si se ha utilizado memoria remota.
Estos valores nunca deben interpretarse de forma aislada, porque Cargas de trabajo reaccionan de forma muy diferente. Los procesos cortos generan fallos aislados, sin alterar de forma apreciable el rendimiento global. Las políticas de intercalación, por su parte, generan asignaciones distribuidas de forma intencionada, lo que hace que aumente el indicador «interleave_hit». Por eso, siempre compruebo la política prevista y la carga actual. Solo entonces decido si un valor requiere una intervención o si se ajusta al diseño.
Para mí, la idea central es la siguiente: Contador Proporcionan señales, no juicios. Busco patrones a lo largo del tiempo, no cifras aisladas. Así es como detecto si un cambio en el sistema desplaza la localidad. Solo a partir de este panorama de tendencias evalúo si debo reubicar procesos, ajustar políticas o establecer restricciones de CPU. Por lo tanto, todo análisis NUMA comienza con una pregunta clara y puntos de medición repetibles.
Interpretar los recuentos de núcleos en su contexto
Siempre comparo numa_hit y compara «numa_miss» entre sí, en lugar de evaluar valores absolutos. Si aumentan los errores, compruebo al mismo tiempo la evolución de «numa_foreign» en los posibles nodos de destino. Si ambos coinciden, esto indica un desplazamiento real y no un mero artefacto de lectura. «local_node» y «other_node» completan este panorama con los accesos reales. Así puedo detectar si una asignación comenzó a nivel local, pero la operación leyó posteriormente memoria más alejada.
Un único alto other_node No me molesta que la carga de trabajo se distribuya de forma deliberada. En cambio, los servidores web con muchos trabajadores se benefician de una localización consistente. Por eso me fijo en los procesos, no solo en la visión global. En cuanto algún servicio se sale de la norma, reviso su ubicación. Solo cuando aumentan los fallos en todo el sistema busco causas relacionadas con la topología o la carga de trabajo.
Comparaciones a lo largo del tiempo: una rutina de medición que da resultados
Tomo las lecturas de los contadores al principio y al final de una Fase final y calculo la diferencia. Los valores individuales ocultan los efectos, mientras que las diferencias revelan la evolución. A menudo bastan intervalos repetidos, por ejemplo, de 30 a 60 segundos, para detectar tendencias. Tras implementaciones, actualizaciones del kernel o cambios de hardware, vuelvo a comparar los mismos intervalos. Si entonces se producen más fallos o se desplaza «local_node», se trata de un cambio real.
Estas series temporales abarcan Error de colocación más rápido que las instantáneas. Correlaciono las líneas con la carga de la CPU, los cambios de contexto y el uso de memoria por nodo. Así puedo ver si los cuellos de botella en la RAM de un nodo provocan movimientos de evasión. O si los nuevos procesos alteran el equilibrio de los nodos. La proporción pura de aciertos y fallos siempre la presento como una evolución, no como una cifra aislada.
Analizar el sistema en su conjunto y, a continuación, profundizar en los procesos
Empiezo con la visión general desde numastat y solo después compruebo los procesos individuales. Este orden ahorra tiempo, ya que muchos efectos se hacen visibles a nivel global. Para la vista de procesos, utilizo la salida específica de cada proceso con el fin de aislar los servicios que llaman la atención. En cuanto se identifican los candidatos, ajusto el Colocación sobre la asignación de CPU y memoria. El artículo sobre este tema recoge una serie de consejos prácticos al respecto: Afinidad de CPU y memoria.
Precisamente en el caso de los servicios Java, PHP-FPM o las bases de datos, a menudo basta con una Afinidad, para reducir significativamente los errores. La orquestación de contenedores tiende a ocultar estos problemas, ya que los programadores distribuyen los recursos sin tener en cuenta la arquitectura NUMA. Por eso, controlo la asignación de nodos por pod o máquina virtual. Si los conjuntos de CPU y la asignación de RAM coinciden, el valor de «local_node» aumenta de forma apreciable. Algunos problemas se resuelven en cuanto el proceso se ejecuta cerca del conjunto de datos necesario.
Resumen de los contadores NUMA (tabla)
Cuando evalúo un nuevo sistema, utilizo la siguiente tabla para poder tener en cuenta cada Cifra clave la clasifico rápidamente. En ella se indican el significado, la interpretación típica y las posibles medidas. No la interpreto como un esquema rígido, sino como una lista de comprobación. Lo fundamental sigue siendo la comparación con el perfil de carga y la topología del servidor. Solo en este contexto puedo tomar una decisión acertada.
| Contador | Significado | interpretación | Acérquese a |
|---|---|---|---|
| numa_hit | Asignación en el nodo deseado | Un valor alto es positivo | Mantener la posición |
| numa_miss | La asignación se ha desviado a otros nodos | Mayor riesgo de latencias | Comprobar la afinidad/política |
| numa_foreign | Asignación externa en este nodo | Contraparte de numa_miss | Analizar los nodos de destino |
| local_node | Accesos a la memoria local | Cuanto más alto, más barato | Proceso más cercano a la RAM |
| other_node | Accesos a la memoria remota | Solo es preocupante si no es intencionado | Comprobar la topología y la carga |
| interleave_hit | Coincidencias en la distribución intercalada | Lo que cabe esperar de la política de intercalación | Evaluar la uniformidad |
Con este Visión general Decido más rápido cuándo intervenir. Un aumento de «numa_miss» sin un cambio explicable desencadena un análisis de las causas. Si los valores de interleave_hit se mantienen altos, compruebo si la política está activa tal y como está previsto. Si other_node muestra un aumento sin que haya aumentado la carga, compruebo si hay cargas de trabajo que lo están desplazando. De este modo, la tabla se convierte en el punto de partida para tomar medidas específicas.
Comprender y utilizar la topología NUMA
Antes de hacer el tuning, compruebo el Topología del servidor: zócalos, núcleos, canales de memoria, rutas de latencia. Si un proceso se ejecuta en el zócalo 0, pero los bloques de trabajo se encuentran en el zócalo 1, aumenta el tiempo de acceso. Esto reduce el rendimiento y provoca fluctuaciones en los tiempos de respuesta. Los servicios que consumen mucha memoria notan especialmente cualquier distancia innecesaria. Por eso, asigno los procesos que consumen muchos datos a nodos con suficiente RAM libre.
Asimétricas Conexiones potencian los efectos, por ejemplo, cuando un nodo utiliza menos canales. En esos casos, traslado de forma selectiva los datos almacenados en caché, en lugar de distribuir el proceso. Configuro los hosts de máquinas virtuales y contenedores de tal manera que cada instancia tenga una asignación de nodo coherente. De este modo, reduzco el tráfico de datos remoto sin limitar las cuotas. Las características físicas de la máquina marcan los límites, y yo me atengo a ellos.
Entender correctamente los conceptos de «interleave» y «balancing»
Las políticas de intercalación distribuyen la memoria de forma deliberada entre los nodos, de modo que Rendimiento aumenta por proceso o disminuyen los puntos críticos. En esta configuración, los valores altos de interleave_hit se consideran deseables. En ese caso, compruebo sobre todo la uniformidad, no la localidad absoluta. AutoNUMA o el equilibrio NUMA pueden ayudar, pero no en todas las situaciones.
Decido según la situación si utilizar la función automática Equilibrio permanece activo. En el caso de servicios consistentes y de larga duración, suelo optar por enlaces fijos. Ante cargas variables, AutoNUMA puede ofrecer una respuesta adecuada. En el artículo se ofrece una buena visión general de las ventajas y los riesgos Equilibrio NUMA. Solo cuando tengo claros el objetivo y el contexto, elijo el modo adecuado.
Patrones de carga de trabajo: bases de datos, máquinas virtuales, servicios web
Las bases de datos son muy sensibles a Latencia entre la CPU y la RAM. Por eso mantengo la instancia, la caché de búfer y los fragmentos activos en el mismo nodo. Las máquinas virtuales se benefician de conjuntos de CPU bien definidos, además de la memoria RAM del nodo, para que los sistemas operativos invitados vean rutas consistentes. Los servicios web con muchos trabajadores funcionan mejor cuando los grupos de trabajadores permanecen vinculados a un único nodo. Para la estrategia de almacenamiento, utilizo, según el caso, medidas específicas Políticas de memoria NUMA.
En cambio, los trabajos analíticos y los escaneos de gran envergadura los realizo en parte distribuido . En este caso, el interleave suele ofrecer mejores anchos de banda que la localidad estricta. Lo importante es analizar con objetividad los patrones de E/S de la carga de trabajo. Las operaciones de escritura predominan frente a las de lectura, y los accesos aleatorios frente a los secuenciales. Elijo la política que se adapta al patrón de acceso, no la que suena bien en los libros de texto.
Rutina práctica de medición y herramientas
Para empezar, me basta con numastat y la vista de procesos. Anoto las lecturas de los contadores con la fecha, el PID y los indicadores de carga. Es importante realizar las mediciones en intervalos de tiempo idénticos. De este modo, se pueden representar con claridad las diferencias entre el antes y el después. En los intervalos productivos, anoto las diferencias y las correlaciono con las fechas de lanzamiento.
En caso de que se observen Servicios Además, compruebo la asignación de la CPU y la visibilidad de los nodos con herramientas como lscpu, numactl y la vista de perf sobre la carga remota. Documento la política elegida en cada ronda de mediciones. Tras un cambio, vuelvo a realizar las mediciones. Solo cuando las líneas de tendencia se estabilizan, considero que el efecto ha sido satisfactorio. Cambiar a ciegas puede dar lugar fácilmente a mejoras aparentes.
Evitar las interpretaciones erróneas más comunes
Un alto interleave_hit No es un error si el intercalado está activado de forma intencionada. Del mismo modo, un único fallo es insignificante si el tiempo de ejecución es largo. Siempre compruebo la densidad y la distribución a lo largo del intervalo, no solo los picos. Hay quien interpreta «other_node» como algo negativo en general y pasa por alto el carácter de la carga de trabajo. Por eso, primero analizo el objetivo de diseño y luego evalúo las cifras.
Otro error: Panorama general Bien, así todo va bien. A menudo, los valores atípicos solo se ocultan en algunos PID. O bien, los programadores de contenedores distribuyen los pods por todos los nodos, aunque lo lógico sería agruparlos localmente. Solo detecto este tipo de efectos cuando mido por proceso. Sin este nivel de detalle, el análisis queda a medias.
Pasos de puesta a punto que marcan la diferencia
Empiezo con Colocación: Procesos en los nodos donde se encuentran o deben encontrarse los datos. A continuación, configuro la afinidad de la CPU para que los hilos no salten de un zócalo a otro. A continuación, configuro la vinculación de memoria para que el núcleo asigne memoria en la ubicación deseada. Para cargas variables, compruebo las políticas y, si es adecuado, utilizo AutoNUMA.
A continuación, me encargo de Coherencia En el ciclo de vida: los reinicios, las implementaciones y los ajustes de escala no deben modificar aleatoriamente las referencias entre nodos. Documento las vinculaciones en forma de código para que sigan siendo reproducibles. A continuación, vuelvo a realizar mediciones, evalúo las variaciones y decido si es necesario realizar ajustes precisos. Cada cambio merece una prueba clara basada en mediciones.
Ejemplo práctico: de fracaso a éxito
Supongamos que una Base de datos Muestra un mayor valor de «numa_miss» y un aumento de «other_node» bajo carga. La latencia de las consultas fluctúa más. Primero compruebo la asignación de procesos y observo que, tras una implementación, el servicio se ejecuta en el nodo A, pero la caché se ha asignado al nodo B. Tras asignar de forma fija la CPU y la memoria al nodo B, la proporción se invierte: el «numa_hit» aumenta y los «misses» disminuyen. Los tiempos de respuesta se vuelven más constantes y la carga de la CPU desciende ligeramente, ya que desaparecen los accesos remotos.
Al mismo tiempo, compruebo la Política. La función «Interleave» se activó de forma involuntaria y distribuyó las asignaciones. Tras cambiar al nodo preferido, la caché permanece cerrada y local. Tras una hora de mediciones, las diferencias confirman la mejora. Solo entonces consideraré que el ajuste ha sido un éxito. Sin esta comprobación cruzada, una instantánea habría sido engañosa.
Métricas y valores de referencia para la práctica
Para tomar decisiones, utilizo criterios sólidos Probabilidades en lugar de valores brutos individuales. Calculo para cada proceso la tasa de asignación local_alloc = numa_hit / (numa_hit + numa_miss). Además, evalúo la Índice de acceso local_access = local_node / (local_node + other_node). Ambos valores juntos indican si la memoria sigue utilizándose de forma local incluso después de la asignación. Como valores orientativos aproximados, me guío por lo siguiente: en el caso de servicios en los que la latencia es crítica, mi objetivo es que los accesos remotos se mantengan por debajo de 5-10 %. En cargas de trabajo analíticas de ancho de banda, tolero entre 20 y 30 %, siempre que aumente el rendimiento. Lo decisivo es la Estabilidad a lo largo del tiempo. Prefiero un valor que se mantenga estable bajo carga a un pico breve con valores perfectos. Anoto estos rangos objetivo en cada revisión, para poder clasificar claramente las mediciones posteriores.
Cgroups, contenedores y problemas con el programador
En entornos de contenedores, lo primero que compruebo es el cpuset‑Asignación: conjuntos de CPU y cpuset.mems Deben abarcar el mismo espacio de nodos; de lo contrario, se producirán inevitablemente fallos. Me aseguro de que los pods con solicitudes fijas de CPU no se extiendan a través de varios nodos NUMA, y de que el programador no distribuya los trabajadores de una misma aplicación de forma dispersa. En el caso de los tipos «burst», limito el número máximo de subprocesos por pod de manera que se mantengan dentro de un mismo nodo. Documento el Dominio NUMA por implementación y exijo réplicas coherentes (un grupo de trabajadores por nodo, no medios grupos repartidos entre dos nodos). Si calculo al límite el tamaño de almacenamiento por pod, me genero una presión innecesaria: un pequeño margen por nodo evita que el kernel tenga que recurrir prematuramente a otros nodos. Si los contenedores se reinician con frecuencia, me aseguro de que el enlace sea determinista, para que Arranques en frío No es casualidad que le hayan asignado una ubicación peor.
Alinear de forma coherente las máquinas virtuales y vNUMA
En el caso de las máquinas virtuales, me centro en vNUMA: La topología virtual debe coincidir con la física. Distribuyo las vCPU de tal forma que cada nodo vNUMA quede asignado a un único nodo NUMA físico. Por parte del host, asigno los subprocesos de QEMU/hipervisor a este dominio y me aseguro de que la memoria RAM asignada se proporcione íntegramente desde este nodo. Vuelo en globo Y acepto el overcommit con cautela en máquinas virtuales en las que la latencia es crítica; un ballooning agresivo puede expulsar los hotsets del nodo y disparar los accesos remotos. En el caso de la migración en vivo, vuelvo a verificar las asignaciones tras el traslado, ya que algunos entornos pierden la asignación precisa de CPU y memoria. Solo cuando la alineación vNUMA está correcta, evalúo numastat en todo el sistema; de lo contrario, estaría solucionando los síntomas, no la causa.
THP, Hugepages y migración de páginas
Páginas enormes transparentes (THP) pueden ser tanto de ayuda como un obstáculo. Las páginas más grandes reducen las faltas de TLB y mejoran el ancho de banda, pero si el núcleo no activa las Hugepages hasta más tarde se derrumba o se migren, pueden aparecer Distancias a gran escala surgen. Me guío por dos reglas: en primer lugar, la Política Definir claramente (por ejemplo, nodo preferido) y, en la medida de lo posible, realizar asignaciones locales de gran tamaño desde el principio. En segundo lugar, en el caso de cargas de trabajo con cachés fijas y de gran tamaño, configuro, siempre que sea posible, «hugepages» estáticas (hugetlb), que reservo explícitamente en un nodo. Esto reduce la fragmentación y los movimientos de compensación. Si observo en las series temporales que, tras un tiempo de ejecución prolongado, el other_node‑A medida que aumenta la proporción, compruebo si Migración de páginas o si se produce compactación y si los ajustes de THP se ajustan al patrón. Para mí es importante no desactivarlo ni activarlo de forma global: lo decido servicio por servicio y mido el efecto en la localidad y la latencia.
Cómo interpretar correctamente los conceptos de «Reclaim», «Swap» y «Memory‑Pressure»
Si las «Misses» suben sin que haya un cambio evidente en su posición, busco presión de almacenamiento por nodo. Los nodos llenos obligan al núcleo a realizar operaciones de recuperación y compactación, en parte provocadas por kswapd en otro nodo, lo que provoca efectos secundarios en los contadores. Compruebo, para cada nodo, la memoria libre y la carga de la caché de páginas. Activado Intercambiar puede desplazar los hotsets y hacer que las latencias se disparen; para servicios especialmente sensibles, desactivo el swap o lo limito estrictamente. En los registros y las vistas de «perf», busco picos de «Reclaim» durante los picos de carga. El objetivo es disponer de suficiente espacio libre, locales Mantener la RAM en el nodo de destino para que las asignaciones no se desplacen. Si para ello es necesario reducir las cachés, doy prioridad al conjunto de trabajo del servicio frente a la caché de páginas genérica.
Comandos prácticos y análisis
Para la visión del proceso utilizo numastat -p y añado: cat /proc//numa_maps, para ver las asignaciones por área (anónimas, respaldadas por archivos) y por nodo. numactl --hardware me proporciona matrices de latencia y tamaños de nodos, lscpu --extended muestra la asignación de la CPU a los nodos. Para los accesos a la memoria centrados en rutas remotas, establezco memoria de rendimiento para verificar los patrones de carga. Recopilo los deltas de forma reproducible, por ejemplo:
Rutina de medición
- t0: guardar numastat (total) y numastat -p para los PID principales
- 30-60 s de ejercicio de esfuerzo, fase de carga idéntica
- t1: volver a leer numastat, calcular los deltas por contador
- Registrar los valores de la CPU en paralelo, los cambios de contexto y los valores de la memoria de los nodos
A continuación, calculo la Probabilidades y señalo qué procesos se desvían significativamente de las tendencias generales del sistema. Cuando persiste la incertidumbre, repito la medición al menos tres veces. Solo considero fiables los desvíos que son consistentes. Para una supervisión continua, asocio los contadores a series temporales y los vinculo con los metadatos de las versiones; de este modo, puedo detectar Puntos de regresión inmediatamente.
Lista de comprobación para un ajuste NUMA sistemático
- Definir el objetivo: latencia frente a rendimiento, carga fija frente a variable
- Captura de la topología: nodos, latencias, reservas de RAM libre por nodo
- Medir los valores de referencia: numastat total y por proceso; calcular los porcentajes
- Corregir la asignación: afinidad de la CPU, vinculación de memoria, políticas
- Configurar contenedores/máquinas virtuales: cpuset.cpus = nodo, cpuset.mems según corresponda; asignar correctamente vNUMA
- Elegir THP/Hugepages de forma consciente, sin perder de vista la fragmentación
- Reducir la presión de memoria: comprobar el margen de memoria por nodo y la estrategia de intercambio
- Medición posterior: comparar los deltas, garantizar la estabilidad a lo largo del tiempo
- Documentación: Enlaces como código, notas de la versión con contexto NUMA
Brevemente resumido
Analizo los datos NUMA mediante Señales En este contexto, véase: pares de contadores, series temporales y vista de procesos. Los valores clave «numa_hit», «numa_miss», «numa_foreign», «local_node», «other_node» e «interleave_hit» me indican la localidad, los movimientos de evasión y las estrategias de distribución. Tomo mis decisiones basándome en la topología y la carga de trabajo, no en valores límite rígidos. El ajuste comienza con la ubicación, la afinidad, una política adecuada y una rutina de medición rigurosa. Así consigo un rendimiento constante Actuación, porque la CPU y la RAM se adaptan a la aplicación y los accesos a datos remotos son poco frecuentes.


