У меня есть 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
linux
ubuntu
performance-tuning
high-load
interrupts
Александр Гладыш
источник
источник
eth1
?Ответы:
Посмотри в
/proc/irq/283
каталоге. Существуетsmp_affinity_list
файл, который показывает, какие процессоры получат прерывание 283. Для вас этот файл, вероятно, содержит «0» (и,smp_affinity
вероятно, содержит «1»).Вы можете записать диапазон CPU в
smp_affinity_list
файл:Или вы можете написать битовую маску, где каждый бит соответствует процессору, чтобы
smp_affinity
:Однако, как известно , у irqbalance есть свое представление о том, какое сходство должно иметь каждое прерывание, и это может отменить ваши обновления. Так что лучше всего полностью удалить irqbalance. Или, по крайней мере, остановить и отключить его при перезагрузке.
Если даже без irqbalance вы становитесь странным
smp_affinity
для прерывания 283 после перезагрузки, вам придется вручную обновлять привязку ЦП в одном из ваших сценариев запуска.источник
irqbalance
уже работает. Может это неправильно настроено? Как это проверить?/proc/irq/283/smp_affinity
есть01
в ней сейчас (никто не менял , что материал на этой машине, насколько мне известно , - так что это должно быть в системе по умолчанию).irqbalance
(черезENABLED=0
in/etc/default/irqbalance
) не помогает. После перезагрузкиirqbalance
естьstop/waiting
, но/proc/irq/283/smp_affinity
все еще есть01
.Если у вас есть подходящая модель Intel NIC, вы можете значительно улучшить производительность.
Цитирую первый абзац:
См. Назначение прерываний для ядер процессора с помощью контроллера Ethernet Intel® 82575/82576 или 82598/82599.
источник
На самом деле , особенно при работе с повторяющимися процессами в течение короткого промежутка времени, рекомендуется, чтобы все прерывания, генерируемые очередью устройства, обрабатывались одним и тем же ЦП, а не балансировкой IRQ, и, таким образом, вы увидите лучшую производительность, если один ЦП обрабатывает прерывание eth1. *** исключение предусмотрено ниже
Ссылка, приведенная выше, взята с Linux Symposium, и я рекомендую вам прочитать пару параграфов по SMP IRQ Affinity, потому что это убедит вас более эффективно, чем этот пост.
Почему?
Напомним, что каждый процессор имеет свой собственный кэш, кроме возможности доступа к основной памяти, ознакомьтесь с этой схемой . Когда прерывание запускается, ядро ЦП должно будет извлечь инструкции для обработки прерывания из основной памяти, что занимает гораздо больше времени, чем если бы инструкции находились в кэше. После того, как процессор выполнил задачу, он будет иметь эти инструкции в кеше. Теперь, скажем, одно и то же ядро ЦП обрабатывает одно и то же прерывание почти все время, функция обработчика прерываний вряд ли покинет кеш ядра ЦП, что повысит производительность ядра.
В качестве альтернативы, когда IRQ сбалансирован, он может назначить прерывание, которое будет постоянно обрабатываться другим ЦП, тогда новое ядро ЦП, вероятно, не будет иметь функцию обработчика прерываний в кеше, и потребуется много времени, чтобы получить правильный обработчик из основного Память.
Исключение : если вы редко используете прерывание eth1, что означает, что прошло достаточно времени, чтобы кэш был перезаписан при выполнении других задач, а это означает, что у вас есть данные, поступающие через этот интерфейс с перерывами в течение длительных периодов времени ... тогда вы, скорее всего, не увидите этих преимуществ потому что они, когда вы используете процесс на высокой частоте.
Вывод
Если ваше прерывание происходит очень часто, просто связывайте это прерывание, чтобы оно обрабатывалось только конкретным процессором. Эта конфигурация живет в
или
См. Последний абзац в разделе SMP IRQ Affinity из источника, указанного выше, в нем есть инструкции.
альтернативно
Вы можете изменить частоту, с которой поднимается флаг прерывания, либо увеличив размер MTU (гигантские кадры), если сеть это позволяет, либо изменив значение флага, повышая его после получения большего количества пакетов вместо каждого пакета ИЛИ изменив тайм-аут, поэтому поднимите прерывание через определенное время. Осторожно с опцией time, потому что размер вашего буфера может быть заполнен до истечения времени. Это можно сделать с помощью ethtool, который описан в связанном источнике.
этот ответ приближается к длине, с которой люди не будут его читать, поэтому я не буду вдаваться в подробности, но в зависимости от вашей ситуации есть много решений ... проверьте источник :)
источник