CPU0 está inundada de interrupciones eth1

12

Tengo una máquina virtual Ubuntu, que se ejecuta dentro de Xen XCP basado en Ubuntu. Aloja un servicio HTTP personalizado basado en FCGI, detrás nginx.

Bajo carga desde ab el primer núcleo de la CPU está saturado, y el resto está subcargado.

En /proc/interruptsveo que CPU0 sirve un orden de magnitud más interrupciones que cualquier otro núcleo. La mayoría de ellos provienen de eth1.

¿Hay algo que pueda hacer para mejorar el rendimiento de esta VM? ¿Hay alguna forma de equilibrar las interrupciones de manera más uniforme?


Detalles sangrientos:

$ uname -a
Linux MYHOST 2.6.38-15-virtual # 59-Ubuntu SMP viernes 27 de abril 16:40:18 UTC 2012 i686 i686 i386 GNU / Linux

$ lsb_release -a
No hay módulos LSB disponibles.
ID de distribuidor: Ubuntu
Descripción: Ubuntu 11.04
Lanzamiento: 11.04
Nombre en clave: natty

$ cat / proc / interrupciones 
           CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7       
283: 113720624 0 0 0 0 0 0 0 xen-dyn-event eth1
284: 1 0 0 0 0 0 0 0 xen-dyn-event eth0
285: 2254 0 0 3873799 0 0 0 0 xen-dyn-event blkif
286: 23 0 0 0 0 0 0 0 xen-dyn-event hvc_console
287: 492 42 0 0 0 0 0 295324 xen-dyn-event xenbus
288: 0 0 0 0 0 0 0 222294 xen-percpu-ipi callfuncsingle7
289: 0 0 0 0 0 0 0 0 xen-percpu-virq debug7
290: 0 0 0 0 0 0 0 151302 xen-percpu-ipi callfunc7
291: 0 0 0 0 0 0 0 3236015 xen-percpu-ipi resched7
292: 0 0 0 0 0 0 0 60064 xen-percpu-ipi spinlock7
293: 0 0 0 0 0 0 0 12355510 temporizador xen-percpu-virq7
294: 0 0 0 0 0 0 803174 0 xen-percpu-ipi callfuncsingle6
295: 0 0 0 0 0 0 0 0 xen-percpu-virq debug6
296: 0 0 0 0 0 0 60027 0 xen-percpu-ipi callfunc6
297: 0 0 0 0 0 0 5374762 0 xen-percpu-ipi resched6
298: 0 0 0 0 0 0 64976 0 xen-percpu-ipi spinlock6
299: 0 0 0 0 0 0 15294870 0 temporizador xen-percpu-virq6
300: 0 0 0 0 0 264441 0 0 xen-percpu-ipi callfuncsingle5
301: 0 0 0 0 0 0 0 0 xen-percpu-virq debug5
302: 0 0 0 0 0 79324 0 0 xen-percpu-ipi callfunc5
303: 0 0 0 0 0 3468144 0 0 xen-percpu-ipi resched5
304: 0 0 0 0 0 66269 0 0 xen-percpu-ipi spinlock5
305: 0 0 0 0 0 12778464 0 0 temporizador xen-percpu-virq5
306: 0 0 0 0 844591 0 0 0 xen-percpu-ipi callfuncsingle4
307: 0 0 0 0 0 0 0 0 xen-percpu-virq debug4
308: 0 0 0 0 75293 0 0 0 xen-percpu-ipi callfunc4
309: 0 0 0 0 3482146 0 0 0 xen-percpu-ipi resched4
310: 0 0 0 0 79312 0 0 0 xen-percpu-ipi spinlock4
311: 0 0 0 0 21642424 0 0 0 xen-percpu-virq timer4
312: 0 0 0 449141 0 0 0 0 xen-percpu-ipi callfuncsingle3
313: 0 0 0 0 0 0 0 0 xen-percpu-virq debug3
314: 0 0 0 95405 0 0 0 0 xen-percpu-ipi callfunc3
315: 0 0 0 3802992 0 0 0 0 xen-percpu-ipi resched3
316: 0 0 0 76607 0 0 0 0 xen-percpu-ipi spinlock3
317: 0 0 0 16439729 0 0 0 0 xen-percpu-virq timer3
318: 0 0 876383 0 0 0 0 0 xen-percpu-ipi callfuncsingle2
319: 0 0 0 0 0 0 0 0 xen-percpu-virq debug2
320: 0 0 76416 0 0 0 0 0 xen-percpu-ipi callfunc2
321: 0 0 3422476 0 0 0 0 0 xen-percpu-ipi resched2
322: 0 0 69217 0 0 0 0 0 xen-percpu-ipi spinlock2
323: 0 0 10247182 0 0 0 0 0 xen-percpu-virq timer2
324: 0 393514 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle1
325: 0 0 0 0 0 0 0 0 xen-percpu-virq debug1
326: 0 95773 0 0 0 0 0 0 xen-percpu-ipi callfunc1
327: 0 3551629 0 0 0 0 0 0 xen-percpu-ipi resched1
328: 0 77823 0 0 0 0 0 0 xen-percpu-ipi spinlock1
329: 0 13784021 0 0 0 0 0 0 xen-percpu-virq timer1
330: 730435 0 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle0
331: 0 0 0 0 0 0 0 0 xen-percpu-virq debug0
332: 39649 0 0 0 0 0 0 0 xen-percpu-ipi callfunc0
333: 3607120 0 0 0 0 0 0 0 xen-percpu-ipi resched0
334: 348740 0 0 0 0 0 0 0 xen-percpu-ipi spinlock0
335: 89912004 0 0 0 0 0 0 0 xen-percpu-virq timer0
NMI: 0 0 0 0 0 0 0 0 Interrupciones no enmascarables
LOC: 0 0 0 0 0 0 0 0 Interrupciones locales del temporizador
SPU: 0 0 0 0 0 0 0 0 Interrupciones espurias
PMI: 0 0 0 0 0 0 0 0 Interrupciones de supervisión del rendimiento
IWI: 0 0 0 0 0 0 0 0 Interrupciones de trabajo IRQ
RES: 3607120 3551629 3422476 3802992 3482146 3468144 5374762 3236015 Reprogramación de interrupciones
CAL: 770084 489287 952799 544546 919884 343765 863201 373596 Interrupciones de llamadas de función
TLB: 0 0 0 0 0 0 0 0 derribos TLB
TRM: 0 0 0 0 0 0 0 0 Interrupciones de eventos térmicos
THR: 0 0 0 0 0 0 0 0 Umbral de interrupciones APIC
MCE: 0 0 0 0 0 0 0 0 Excepciones de verificación de máquina
MCP: 0 0 0 0 0 0 0 0 Encuestas de verificación de máquinas
ERR: 0
SIG: 0
Alexander Gladysh
fuente
Pregunta adicional: ¿hay alguna manera de disminuir el número de interrupciones eth1?
Alexander Gladysh

Respuestas:

10

Mira en el /proc/irq/283directorio. Hay un smp_affinity_listarchivo que muestra qué CPU obtendrán la interrupción 283. Para usted, este archivo probablemente contiene "0" (y smp_affinityprobablemente contiene "1").

Puede escribir el rango de CPU en el smp_affinity_listarchivo:

echo 0-7 | sudo tee /proc/irq/283/smp_affinity_list

O puede escribir una máscara de bits, donde cada bit corresponde a una CPU, para smp_affinity:

printf %x $((2**8-1)) | sudo tee /proc/irq/283/smp_affinity

Sin embargo, se sabe que irqbalance tiene su propia idea de la afinidad que debe tener cada interrupción, y podría revertir sus actualizaciones. Por lo tanto, es mejor si simplemente desinstala irqbalance por completo. O al menos deténgalo y desactívelo para que no se reinicie.

Si incluso sin irqbalance se vuelve extraño smp_affinitypor la interrupción 283 después de un reinicio, deberá actualizar manualmente la afinidad de la CPU en uno de sus scripts de inicio.

chutz
fuente
irqbalanceYa se está ejecutando. Tal vez no está configurado correctamente? ¿Cómo verificar eso?
Alexander Gladysh
Tal vez debería deshabilitar irqbalance, reiniciar, ver si eso ayuda. Las interrupciones están bastante bien equilibradas por defecto.
chutz el
FYI: /proc/irq/283/smp_affinitytiene 01en él ahora (nadie ha cambiado esas cosas en esta máquina a lo mejor de mi conocimiento, por lo que esto debe ser el sistema predeterminado).
Alexander Gladysh
Lo siento, actualicé mi respuesta. irqbalance es probablemente el culpable. Solo deshazte de eso. No sé cuál se supone que es el valor predeterminado, pero por experiencia lo he visto predeterminado en "TODAS LAS CPU".
chutz el
Deshabilitar irqbalance(vía ENABLED=0adentro /etc/default/irqbalance) no ayuda. Después de reiniciar irqbalancees stop/waiting, pero /proc/irq/283/smp_affinitysigue siendo 01.
Alexander Gladysh
2

Si tiene el modelo correcto de Intel NIC, puede mejorar significativamente el rendimiento.

Para citar el primer párrafo:

Los procesadores multinúcleo y los adaptadores Ethernet más nuevos (incluidos los 82575, 82576, 82598 y 82599) permiten optimizar los flujos de reenvío TCP mediante la asignación de flujos de ejecución a núcleos individuales. Por defecto, Linux asigna automáticamente interrupciones a los núcleos del procesador. Actualmente existen dos métodos para asignar automáticamente las interrupciones, un equilibrador IRQ inkernel y el daemon de equilibrio IRQ en el espacio del usuario. Ambos ofrecen compensaciones que pueden reducir el uso de la CPU pero no maximizan las tasas de reenvío de IP. Se puede obtener un rendimiento óptimo al anclar manualmente las colas del adaptador Ethernet a núcleos de procesador específicos.

Para el reenvío de IP, un par de cola de transmisión / recepción debe usar el mismo núcleo de procesador y reducir cualquier sincronización de caché entre diferentes núcleos. Esto se puede realizar asignando interrupciones de transmisión y recepción a núcleos específicos. Comenzando con el kernel de Linux 2.6.27, se pueden usar múltiples colas en 82575, 82576, 82598 y 82599. Además, se habilitaron múltiples colas de transmisión en Interrupciones señalizadas de mensajería extendida (MSI-X). MSI-X admite una mayor cantidad de interrupciones que se pueden utilizar, lo que permite un control más preciso y la orientación de las interrupciones a CPU específicas.

Consulte: Asignación de interrupciones a núcleos de procesador mediante un controlador Ethernet Intel® 82575/82576 o 82598/82599

Mate
fuente
2

En realidad , se recomienda, especialmente cuando se trata de procesos repetitivos de corta duración, que todas las interrupciones generadas por una cola de dispositivo sean manejadas por la misma CPU, en lugar del equilibrio de IRQ y, por lo tanto, verá un mejor rendimiento si una sola CPU maneja la interrupción eth1 *** excepción proporcionada a continuación

La fuente, vinculada anteriormente, es del Simposio de Linux y le recomiendo que lea los dos párrafos sobre SMP IRQ Affinity porque lo convencerá más efectivamente que esta publicación.

¿Por qué?

Recuerde que cada procesador tiene su propia memoria caché además de poder acceder a la memoria principal, consulte este diagrama . Cuando se dispara una interrupción, el núcleo de la CPU tendrá que buscar las instrucciones para manejar la interrupción desde la memoria principal, lo que lleva mucho más tiempo que si las instrucciones estuvieran en el caché. Una vez que un procesador ejecuta una tarea, tendrá esas instrucciones en la memoria caché. Ahora, digamos que el mismo núcleo de la CPU maneja la misma interrupción casi todo el tiempo, la función del controlador de interrupciones probablemente no saldrá del caché del núcleo de la CPU, lo que aumentará el rendimiento del kernel.

Alternativamente, cuando IRQ está equilibrado, puede asignar la interrupción para ser manejada constantemente por diferentes CPU, entonces el nuevo núcleo de la CPU probablemente no tendrá la función de manejo de interrupciones en el caché, y se requerirá mucho tiempo para obtener el manejador adecuado de main memoria.

Excepción : si rara vez usa la interrupción eth1, lo que significa que pasa el tiempo suficiente para que el caché se sobrescriba al realizar otras tareas, lo que significa que tiene datos que provienen de esa interfaz de forma intermitente con largos períodos intermedios ... entonces lo más probable es que no vea estos beneficios porque son cuando usas un proceso en alta frecuencia.

Conclusión

Si su interrupción ocurre con mucha frecuencia, entonces solo enlace esa interrupción para ser manejada por una CPU específica solamente. Esta configuración vive en

 /proc/'IRQ number'/smp_affinity

o

/proc/irq/'IRQ number'/smp_affinity

Vea el último párrafo en la sección de afinidad SMP IRQ de la fuente vinculada anteriormente, tiene instrucciones.

Alternativamente

Puede cambiar la frecuencia con la que se activa el indicador de interrupción aumentando el tamaño de MTU (tramas gigantes) si la red lo permite o cambiar para que se active el indicador después de recibir una mayor cantidad de paquetes en lugar de en cada paquete O cambiar el tiempo de espera, así que aumenta la interrupción después de un cierto período de tiempo. Tenga cuidado con la opción de tiempo porque el tamaño de su búfer podría estar lleno antes de que se agote el tiempo. Esto se puede hacer utilizando la herramienta ethtool que se describe en la fuente vinculada.

esta respuesta se acerca a la longitud en que la gente no la leerá, así que no entraré en muchos detalles, pero dependiendo de su situación, hay muchas soluciones ... verifique la fuente :)

hermano-bilo
fuente