Eu tenho uma VM do Ubuntu, rodando dentro do Xen XCP baseado no Ubuntu. Ele hospeda um serviço HTTP personalizado baseado em FCGI, por trás nginx
.
A carga insuficiente do primeiro núcleo da CPU está saturada e o restante está sobrecarregado ab
.
Em /proc/interrupts
vejo que CPU0 serve uma ordem de magnitude mais interrupções do que qualquer outro núcleo. A maioria deles vem eth1
.
Há algo que eu possa fazer para melhorar o desempenho desta VM? Existe uma maneira de equilibrar as interrupções de maneira mais uniforme?
Detalhes sangrentos:
$ uname -a Linux MYHOST 2.6.38-15-virtual # 59-Ubuntu SMP Sex Abr 27 16:40:18 UTC 2012 i686 i686 i386 GNU / Linux $ lsb_release -a Nenhum módulo LSB está disponível. ID do Distribuidor: Ubuntu Descrição: Ubuntu 11.04 Lançamento: 11.04 Nome de código: natty $ cat / proc / interrompe 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 xen-percpu-virq timer7 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 xen-percpu-virq timer6 300: 0 0 0 0 0 264441 0 0 xen-percpu-ipi callfuncsingle5 301: 0 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 xen-percpu-virq timer5 306: 0 0 0 0 844591 0 0 0 xen-percpu-ipi callfuncsingle4 307: 0 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 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 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 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 0 Interrupções não mascaráveis LOC: 0 0 0 0 0 0 0 0 0 Temporizador local interrompe SPU: 0 0 0 0 0 0 0 0 0 Interrupções espúrias PMI: 0 0 0 0 0 0 0 0 0 O monitoramento de desempenho interrompe IWI: 0 0 0 0 0 0 0 0 0 trabalho de IRQ interrompe RES: 3607120 3551629 3422476 3802992 3482146 3468144 5374762 3236015 Reagendar interrupções CAL: 770084 489287 952799 544546 919884 343765 863201 373596 Interrupção de chamada de função TLB: 0 0 0 0 0 0 0 0 0 abates TLB TRM: 0 0 0 0 0 0 0 0 0 Evento térmico interrompe THR: 0 0 0 0 0 0 0 0 0 Limiar APIC interrompe MCE: 0 0 0 0 0 0 0 0 0 Exceções de verificação da máquina MCP: 0 0 0 0 0 0 0 0 0 Pesquisas de verificação de máquina ERR: 0 MIS: 0
linux
ubuntu
performance-tuning
high-load
interrupts
Alexander Gladysh
fonte
fonte
eth1
?Respostas:
Procure no
/proc/irq/283
diretório Há umsmp_affinity_list
arquivo que mostra quais CPUs receberão a interrupção 283. Para você, esse arquivo provavelmente contém "0" (esmp_affinity
provavelmente contém "1").Você pode gravar o intervalo da CPU no
smp_affinity_list
arquivo:Ou você pode escrever uma máscara de bits, onde cada bit corresponde a uma CPU, para
smp_affinity
:No entanto, sabe- se que o irqbalance tem sua própria idéia de qual afinidade cada interrupção deve ter e pode reverter suas atualizações. Portanto, é melhor se você desinstalar completamente o irqbalance. Ou pelo menos pare e desative o reinício.
Se mesmo sem o irqbalance você estiver com problemas
smp_affinity
de interrupção após uma reinicialização, precisará atualizar manualmente a afinidade da CPU em um dos scripts de inicialização.fonte
irqbalance
já está em execução. Talvez não esteja configurado corretamente? Como verificar isso?/proc/irq/283/smp_affinity
já está01
nele (ninguém mudou essas coisas nesta máquina com o melhor de meu conhecimento - portanto, esse deve ser o padrão do sistema).irqbalance
(viaENABLED=0
em/etc/default/irqbalance
) não ajuda. Após a reinicializaçãoirqbalance
éstop/waiting
, mas/proc/irq/283/smp_affinity
ainda é01
.Se você possui o modelo certo da Intel NIC, pode melhorar significativamente o desempenho.
Para citar o primeiro parágrafo:
Consulte: Atribuindo interrupções aos núcleos do processador usando um controlador Ethernet Intel® 82575/82576 ou 82598/82599 Ethernet
fonte
Na verdade , é recomendável, especialmente ao lidar com processos repetitivos por um curto período, que todas as interrupções geradas por uma fila de dispositivos sejam tratadas pela mesma CPU, em vez do balanceamento de IRQ e, portanto, você terá melhor desempenho se uma única CPU manipular a interrupção eth1 *** exceção fornecida abaixo
A fonte, vinculada acima, é do Linux Symposium e eu recomendo que você leia os dois parágrafos sobre o SMP IRQ Affinity, porque o convencerá com mais eficácia do que esta publicação.
Por quê?
Lembre-se de que cada processador possui seu próprio cache, além de poder acessar a memória principal, consulte este diagrama . Quando uma interrupção é acionada, o núcleo da CPU precisará buscar as instruções para lidar com a interrupção da memória principal, o que leva muito mais tempo do que se as instruções estivessem no cache. Depois que um processador executa uma tarefa, essas instruções estão no cache. Agora, digamos que o mesmo núcleo da CPU lide com a mesma interrupção quase o tempo todo, a função do manipulador de interrupções provavelmente não sairá do cache do núcleo da CPU, aumentando o desempenho do kernel.
Como alternativa, quando o IRQ é balanceado, ele pode atribuir a interrupção a ser tratada constantemente por uma CPU diferente, então o novo núcleo da CPU provavelmente não terá a função de manipulador de interrupção no cache, e será necessário muito tempo para obter o manipulador apropriado da main memória.
Exceção : se você raramente está usando a interrupção eth1, significa que há tempo suficiente para que o cache seja sobrescrito por outras tarefas, o que significa que há dados provenientes dessa interface de forma intermitente com longos períodos no meio ... então você provavelmente não verá esses benefícios pois eles são quando você usa um processo em alta frequência.
Conclusão
Se sua interrupção ocorrer com muita frequência, basta vincular essa interrupção a ser tratada apenas por uma CPU específica. Essa configuração vive em
ou
Consulte o último parágrafo na seção SMP IRQ Affinity da fonte vinculada acima, e possui instruções.
alternativamente
Você pode alterar a frequência com que o sinalizador de interrupção é aumentado aumentando o tamanho da MTU (jumbo-frames) se a rede permitir ou alterar o sinalizador após o recebimento de uma quantidade maior de pacotes em vez de em cada pacote OU alterar o tempo limite, então aumente a interrupção após um certo período de tempo. Cuidado com a opção de hora, pois o tamanho do buffer pode estar cheio antes que o tempo acabe. Isso pode ser feito usando o ethtool descrito na fonte vinculada.
esta resposta está se aproximando do comprimento em que as pessoas não leem, então não entrarei em muitos detalhes, mas, dependendo da sua situação, existem muitas soluções ... verifique a fonte :)
fonte