Назад | Перейти на главную страницу

CPU0 завален прерываниями eth1

У меня есть виртуальная машина Ubuntu, работающая внутри Xen XCP на базе Ubuntu. На нем размещается настраиваемая HTTP-служба на основе FCGI за nginx.

Под нагрузкой от ab первое ядро ​​процессора перегружено, а остальные недогружены.

В /proc/interrupts я вижу это CPU0 обслуживает на порядок больше прерываний, чем любое другое ядро. Большинство из них происходят из eth1.

Что я могу сделать для повышения производительности этой виртуальной машины? Есть ли способ более равномерно сбалансировать прерывания?


Кровавые подробности:

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

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.04
Release:    11.04
Codename:   natty

$ cat /proc/interrupts 
           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  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  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   Non-maskable interrupts
LOC:          0          0          0          0          0          0          0          0   Local timer interrupts
SPU:          0          0          0          0          0          0          0          0   Spurious interrupts
PMI:          0          0          0          0          0          0          0          0   Performance monitoring interrupts
IWI:          0          0          0          0          0          0          0          0   IRQ work interrupts
RES:    3607120    3551629    3422476    3802992    3482146    3468144    5374762    3236015   Rescheduling interrupts
CAL:     770084     489287     952799     544546     919884     343765     863201     373596   Function call interrupts
TLB:          0          0          0          0          0          0          0          0   TLB shootdowns
TRM:          0          0          0          0          0          0          0          0   Thermal event interrupts
THR:          0          0          0          0          0          0          0          0   Threshold APIC interrupts
MCE:          0          0          0          0          0          0          0          0   Machine check exceptions
MCP:          0          0          0          0          0          0          0          0   Machine check polls
ERR:          0
MIS:          0

Посмотрите в /proc/irq/283 каталог. Eсть smp_affinity_list файл, который показывает, какие процессоры получат прерывание 283. Для вас этот файл, вероятно, содержит "0" (и smp_affinity вероятно содержит "1").

Вы можете записать диапазон ЦП в smp_affinity_list файл:

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

Или вы можете написать битовую маску, где каждый бит соответствует процессору, чтобы smp_affinity:

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

Тем не мение, irqbalance известно, что он имеет собственное представление о том, какое сродство должно иметь каждое прерывание, и может отменить ваши обновления. Так что лучше всего полностью удалить irqbalance. Или, по крайней мере, остановите его и отключите от перезагрузки.

Если даже без irqbalance вы получаете лишний smp_affinity для прерывания 283 после перезагрузки вам придется вручную обновить соответствие ЦП в одном из ваших сценариев запуска.

Фактически рекомендуется, особенно при работе с повторяющимися процессами в течение короткого времени, чтобы все прерывания, генерируемые очередью устройства, обрабатывались одним и тем же процессором, а не балансировкой IRQ и, следовательно, вы увидите лучшую производительность, если один процессор обработал исключение прерывания eth1 ***, указанное ниже

Источник, указанный выше, взят с Симпозиума Linux, и я рекомендую вам прочитать пару абзацев на SMP IRQ Affinity потому что это убедит вас более эффективно, чем этот пост.

Зачем?

Напомним, что у каждого процессора есть собственный кеш, помимо возможности доступа к основной памяти, проверьте эту диаграмму. Когда запускается прерывание, ядро ​​ЦП должно будет получить инструкции для обработки прерывания из основной памяти, что занимает гораздо больше времени, чем если бы инструкции были в кеше. После того, как процессор выполнит задачу, он будет иметь эти инструкции в кеше. Теперь предположим, что одно и то же ядро ​​ЦП почти все время обрабатывает одно и то же прерывание, функция обработчика прерываний вряд ли покинет кеш ядра ЦП, увеличивая производительность ядра.

В качестве альтернативы, когда IRQ сбалансирован, он может назначить прерывание, которое будет обрабатываться постоянно другим ЦП, тогда новое ядро ​​ЦП, вероятно, не будет иметь функции обработчика прерывания в кэше, и потребуется много времени, чтобы получить правильный обработчик из основного объем памяти.

Исключение: если вы редко используете прерывание eth1, что означает, что проходит достаточно времени, чтобы кеш был перезаписан при выполнении других задач, что означает, что у вас есть данные, периодически поступающие через этот интерфейс с длительными периодами между ними ... тогда вы, скорее всего, не увидите этих преимуществ для они есть, когда вы используете процесс с высокой частотой.

Вывод

Если ваше прерывание происходит очень часто тогда просто привязывайте это прерывание для обработки только определенным процессором. Эта конфигурация находится в

 /proc/'IRQ number'/smp_affinity

или

/proc/irq/'IRQ number'/smp_affinity

См. Последний абзац в SMP IRQ Affinity из источника, указанного выше, в нем есть инструкции.

Альтернативно

Вы можете изменить частоту срабатывания флага прерывания, либо увеличив размер MTU (jumbo-кадры), если это позволяет сеть, либо изменив так, чтобы флаг поднимался после получения большего количества пакетов вместо каждого пакета, ИЛИ изменив значение тайм-аут, поэтому увеличьте прерывание через определенное время. Будьте осторожны с опцией времени, потому что ваш буфер может быть заполнен до того, как истечет время. Это можно сделать с помощью эттоол который указан в связанном источнике.

этот ответ приближается к тому времени, когда люди не будут его читать, поэтому я не буду вдаваться в подробности, но в зависимости от вашей ситуации есть много решений ... проверьте источник :)

Если у вас есть подходящая модель сетевой карты Intel, вы можете значительно повысить производительность.

Процитируем первый абзац:

Многоядерные процессоры и новейшие адаптеры Ethernet (включая 82575, 82576, 82598 и 82599) позволяют оптимизировать потоки пересылки TCP путем назначения потоков выполнения отдельным ядрам. По умолчанию Linux автоматически назначает прерывания ядрам процессора. В настоящее время существуют два метода автоматического назначения прерываний: внутренний балансировщик IRQ и демон балансировки IRQ в пространстве пользователя. Оба предлагают компромиссы, которые могут снизить использование ЦП, но не максимизируют скорость пересылки IP. Оптимальную пропускную способность можно получить, вручную привязав очереди адаптера Ethernet к определенным ядрам процессора.

Для переадресации IP пара очереди передачи / приема должна использовать одно и то же ядро ​​процессора и уменьшать любую синхронизацию кэша между разными ядрами. Это может быть выполнено путем назначения прерываний передачи и приема определенным ядрам. Начиная с ядра Linux 2.6.27, несколько очередей можно использовать на 82575, 82576, 82598 и 82599. Кроме того, несколько очередей передачи были включены в сигнальных прерываниях расширенного обмена сообщениями (MSI-X). MSI-X поддерживает большее количество прерываний, которые можно использовать, что позволяет более детально управлять и нацеливать прерывания на определенные ЦП.

Видеть: Назначение прерываний ядрам процессора с помощью контроллера Ethernet Intel® 82575/82576 или 82598/82599