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

12

У меня есть Ubuntu VM, работающая внутри Xen XCP на основе Ubuntu. За ним стоит собственный HTTP-сервис на основе FCGI nginx.

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

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

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


Гор детали:

$ uname -a
Linux MYHOST 2.6.38-15-virtual # 59-Ubuntu SMP пт 27 апреля 16:40:18 UTC 2012 i686 i686 i386 GNU / Linux

$ lsb_release -a
Модули LSB не доступны.
Идентификатор распространителя: Ubuntu
Описание: Ubuntu 11.04
Релиз: 11.04
Кодовое название: 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-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 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 Немаскируемые прерывания
LOC: 0 0 0 0 0 0 0 0 Прерывания локального таймера
SPU: 0 0 0 0 0 0 0 0 Ложные прерывания
PMI: 0 0 0 0 0 0 0 0 Прерывания контроля производительности
IWI: 0 0 0 0 0 0 0 0 прерывания работы IRQ
RES: 3607120 3551629 3422476 3802992 3482146 3468144 5374762 3236015 Перепланирование прерываний
CAL: 770084 489287 952799 544546 919884 343765 863201 373596 Прерывания вызова функции
TLB: 0 0 0 0 0 0 0 0 TLB перестрелки
TRM: 0 0 0 0 0 0 0 0 Прерывания теплового события
THR: 0 0 0 0 0 0 0 0 Пороговые прерывания APIC
MCE: 0 0 0 0 0 0 0 0 Машинная проверка исключений
MCP: 0 0 0 0 0 0 0 0 Машинные проверки опросов
ERR: 0
MIS: 0
Александр Гладыш
источник
Бонусный вопрос: есть ли способ уменьшить количество прерываний от eth1?
Александр Гладыш

Ответы:

10

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

Вы можете записать диапазон CPU в 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 после перезагрузки, вам придется вручную обновлять привязку ЦП в одном из ваших сценариев запуска.

chutz
источник
irqbalanceуже работает. Может это неправильно настроено? Как это проверить?
Александр Гладыш
Может быть, вам следует просто отключить irqbalance, перезагрузиться, посмотреть, поможет ли это. Прерывания довольно хорошо сбалансированы по умолчанию.
Chutz
FYI: /proc/irq/283/smp_affinityесть 01в ней сейчас (никто не менял , что материал на этой машине, насколько мне известно , - так что это должно быть в системе по умолчанию).
Александр Гладыш
Извините, я обновил свой ответ. Несбалансированность, вероятно, является виновником. Просто избавься от этого. Я не знаю, каким должно быть значение по умолчанию, но по опыту я видел, что по умолчанию установлено значение «ВСЕ ЦП».
Chutz
Отключение irqbalance(через ENABLED=0in /etc/default/irqbalance) не помогает. После перезагрузки irqbalanceесть stop/waiting, но /proc/irq/283/smp_affinityвсе еще есть 01.
Александр Гладыш
2

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

Цитирую первый абзац:

Многоядерные процессоры и новейшие адаптеры 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.

Matt
источник
2

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

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

Почему?

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

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

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

Вывод

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

 /proc/'IRQ number'/smp_affinity

или

/proc/irq/'IRQ number'/smp_affinity

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

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

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

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

брат-било
источник