Не многие знают, что они могут значительно повысить производительность сетевой подсистемы Linux на мультипроцессорных или многоядерных системах за счёт распределения системных прерываний от сетевых адаптеров на различные процессоры/ядра.
Дело в том, что при интенсивной сетевой нагрузке сетевые платы вызывают слишком много системных прерываний (Вы можете посмотреть нагрузку на процессоры Вашего сервера создаваемую обработкой системных прерываний с помощью утилиты top – параметр si), что влечёт за собой потерю пакетов проходящих на/через сетевые интерфейсы.
Допустим, что у Вас в системе есть два процессора и два сетевых адаптера, сделаем так, чтобы системные прерывания от eth0 обрабатывались первым процессором, а прерывания от второго сетевого адаптера eth1 обрабатывались вторым процессором.
Проверим как обрабатываются прерывания от сетевых адаптеров в данный момент: cat /proc/interrupts
CPU0 CPU1 0: 1025359421 1011223877 IO-APIC-edge timer 1: 7 443237 IO-APIC-edge i8042 6: 3 2 IO-APIC-edge floppy 7: 0 0 IO-APIC-edge parport0 8: 0 18718112 IO-APIC-edge rtc 9: 1 0 IO-APIC-level acpi 12: 11950434 756 IO-APIC-edge i8042 90: 790345 0 IO-APIC-level eth0 169: 69 10339595 IO-APIC-level uhci_hcd:usb5, HDA Intel, i915@pci:0000:00:02.0 177: 79073095 0 IO-APIC-level eth1 209: 0 0 IO-APIC-level uhci_hcd:usb4 217: 212348 1 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb2 225: 24498064 3245 IO-APIC-level uhci_hcd:usb3, libata NMI: 0 0 LOC: 2036559271 2036559270 ERR: 0 MIS: 0
как мы можем видеть в приведённом примере первый сетевого адаптер «висит» на IRQ 90, а второй на IRQ 177. Причём явно видно что прерывания как от первого, так и второго сетевого адаптера обрабатываются первым процессором в системе.
Исправим данную ситуацию, для этого нам необходимо записать число “2″ в файл /proc/irq/177/smp_affinity
echo "2" >/proc/irq/177/smp_affinity
после этого посмотрим как изменилась ситуация:
cat /proc/interrupts
CPU0 CPU1
0: 1025359421 1011223877 IO-APIC-edge timer
1: 7 443237 IO-APIC-edge i8042
6: 3 2 IO-APIC-edge floppy
7: 0 0 IO-APIC-edge parport0
8: 0 18718112 IO-APIC-edge rtc
9: 1 0 IO-APIC-level acpi
12: 11950434 756 IO-APIC-edge i8042
90: 790345 0 IO-APIC-level eth0
169: 69 10339595 IO-APIC-level uhci_hcd:usb5, HDA Intel, i915@pci:0000:00:02.0
177: 79073095 3672362 IO-APIC-level eth1
209: 0 0 IO-APIC-level uhci_hcd:usb4
217: 212348 1 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb2
225: 24498064 3245 IO-APIC-level uhci_hcd:usb3, libata
NMI: 0 0
LOC: 2036559271 2036559270
ERR: 0
MIS: 0
как видим счётчик прерываний для eth1 на CPU0 не изменился, но появились цифры ниже CPU1 т.е. обработка прерываний от второго сетевого адаптера eth1 обрабатывается вторым процессором в системе.
Небольшое объяснение насчёт того, что же значит цифра 2 !
Linux каждому cpu в системе ставит в соответствие некую цифру обозначающую данный процессор в системе. Ниже приведена таблица для 4-х процессорной системы
двоичный шестнадцатеричный
CPU 0 0001 1
CPU 1 0010 2
CPU 2 0100 4
CPU 3 1000 8
т.е. если бы у нас в вышеприведённом примере было не 2 а четыре процессора и мы бы хотели обрабатывать прерывания от eth1 на третьем процессоре CPU2, то нам для этого пришлось бы вместо 2 записать цифру 4 в файл /proc/irq/177/smp_affinity .
Любознательный читатель может спросить, что же было бы если бы мы записали в данный файл число которого нет в приведённой таблице, например echo “3″ >/proc/irq/177/smp_affinity. Ответ прост прерывания от eth1 обрабатывались бы первым и вторым процессором т.к.
двоичный шестнадцатеричный
CPU 0 0001 1
+ CPU 2 0010 2
-----------------------
0011 3
Стоит особо отметить, нет смысла обрабатывать системные прерывания от одного сетевого адаптера на нескольких процессорах/ядрах т.к. суммарно system interrupts от данного адаптера никогда не превысит 100%, т.е. максимум, что Вы сможете получить это 50% загрузки на одном процессоре/ядре и 50% на другом.
Дополнение: у компании Intel существуют чипсеты 82575 и 82576 сетевые карты на базе которых имеют несколько очередей каждая из которых может обрабатываться отдельным ядром/процессором.
Выглядит это следующим образом
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
0: 72718527 72693470 72701000 72694778 72698856 72705975 72697612 72709066 IO-APIC-edge timer
1: 0 1 0 0 0 0 1 0 IO-APIC-edge i8042
6: 0 0 2 0 0 0 1 0 IO-APIC-edge floppy
8: 0 0 0 0 0 1 0 0 IO-APIC-edge rtc
9: 0 0 0 0 0 0 0 1 IO-APIC-level acpi
14: 143672 144923 144966 146156 144955 144426 144156 144955 IO-APIC-edge ata_piix
15: 892735 915776 908202 913235 910358 903767 912399 900143 IO-APIC-edge ide1
58: 0 0 0 0 0 0 0 0 IO-APIC-level uhci_hcd:usb3
66: 64 0 0 2259148530 0 0 0 0 PCI-MSI-X eth0-tx0
74: 2992330737 0 0 0 0 0 0 0 PCI-MSI-X eth0-rx0
82: 4197 3028991669 0 0 0 0 0 0 PCI-MSI-X eth0-rx1
90: 4091 0 3008220806 0 0 0 0 0 PCI-MSI-X eth0-rx2
98: 4092 0 0 2999334745 0 0 0 0 PCI-MSI-X eth0-rx3
106: 2 0 0 0 0 0 0 0 PCI-MSI-X eth0
114: 7 0 0 0 0 0 0 2265679966 PCI-MSI-X eth1-tx0
122: 1 0 0 0 3906833163 0 0 0 PCI-MSI-X eth1-rx0
130: 1 0 0 0 0 3957703625 0 0 PCI-MSI-X eth1-rx1
138: 1 0 0 0 0 0 3918250115 0 PCI-MSI-X eth1-rx2
146: 1 0 0 0 0 0 0 3928688764 PCI-MSI-X eth1-rx3
154: 2 0 0 0 0 0 0 0 PCI-MSI-X eth1
169: 0 0 0 0 0 0 0 0 IO-APIC-level uhci_hcd:usb5
177: 1 0 0 0 1 1 1 1 IO-APIC-level uhci_hcd:usb4, aic94xx
185: 0 0 0 0 0 0 0 0 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb2
NMI: 0 0 0 0 0 0 0 0
LOC: 581643579 581643516 581643609 581643411 581643494 581643475 581643531 581643008
ERR: 0
MIS: 0
За данную информацию спасибо Marian Ivasiuk
Подробнее прочитать о SMP-Affinity можно по этому адресу http://www.cs.uwaterloo.ca/~brecht/servers/apic/SMP-affinity.txt
http://centos.alt.ru/?p=26