Моя цель - настроить наши серверы CentOS («бесплатный» RHEL) 5.x для пользовательских сетевых программ с малой задержкой. Я хотел бы поэкспериментировать с привязкой обработки прерываний сетевого адаптера Ethernet к тому же процессору, на котором работает программа (чтобы, надеюсь, улучшить использование кеша). Первым шагом в этом процессе является определение IRQ сетевого адаптера.
Вот содержимое / proc / interrupts на одном сервере (обратите внимание, что для краткости я удалил ЦП с 2 по 14):
CPU0 CPU1 CPU15
0: 600299726 0 0 IO-APIC-edge timer
1: 3 0 0 IO-APIC-edge i8042
8: 1 0 0 IO-APIC-edge rtc
9: 0 0 0 IO-APIC-level acpi
12: 4 0 0 IO-APIC-edge i8042
50: 0 0 0 IO-APIC-level uhci_hcd:usb6, uhci_hcd:usb8
58: 6644 25103 0 IO-APIC-level ioc0
66: 0 0 0 IO-APIC-level ata_piix
74: 221 533830 0 IO-APIC-level ata_piix
98: 35 0 2902361 PCI-MSI-X eth1-0
106: 61 11 3841 PCI-MSI-X eth1-1
114: 28 0 61452 PCI-MSI-X eth1-2
122: 24 1586 22 PCI-MSI-X eth1-3
130: 2912 0 337 PCI-MSI-X eth1-4
138: 21 0 28 PCI-MSI-X eth1-5
146: 21 0 56 PCI-MSI-X eth1-6
154: 34 1 1 PCI-MSI-X eth1-7
209: 23 0 0 IO-APIC-level ehci_hcd:usb1
217: 0 0 0 IO-APIC-level ehci_hcd:usb2, uhci_hcd:usb5, uhci_hcd:usb7
225: 0 0 0 IO-APIC-level uhci_hcd:usb3
233: 0 0 0 IO-APIC-level uhci_hcd:usb4
NMI: 7615 2989 2931
LOC: 600328144 600328099 600327086
ERR: 0
MIS: 0
Почему существует несколько записей для "eth1" в форме "eth1-X"?
Кроме того, содержимое «/ sys / class / net / eth1 / device / irq» равно «90». Но в приведенном выше списке прерываний нет 90.
Допустим, я смотрю только на "eth1-0", то есть на IRQ 98. Содержимое / proc / irq / 98 / smp_affinity:
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00008000
Это список чисел, а не просто одно число.
Итак, как мне установить smp_affinity для eth1?
Ни в одном из онлайн-примеров и документации, которые мне удалось найти, не упоминались подобные случаи; у них всегда есть ровно одна запись "ethX" в / proc / interrupts; указанное прерывание соответствует / sys / class / net / ethX / device / irq; а в / proc / irq / N / smp_affinity только одно число.
FWIW, добавлю, что это приложение чрезвычайно чувствительность к задержке. До такой степени, что мы отключаем C-состояния и масштабирование частоты процессора (потому что эти функции вызывают слишком большую задержку). Микро секунды имеют значение здесь.
редактировать: Я наткнулся на следующую веб-страницу http://www.kernel.org/doc/man-pages/online/pages/man7/cpuset.7.html что, хотя речь идет о cpuset, в нем есть раздел под названием "Формат маски", который я предполагать то же самое, что я вижу в файле / proc / irq // smp_affinity. Цитата:
В этом формате каждое 32-битное слово отображается в шестнадцатеричном формате (с использованием символов ASCII «0» - «9» и «a» - «f»); слова при необходимости заполняются ведущими нулями. Для масок, состоящих из более чем одного слова, между словами используется запятая. Слова отображаются в порядке обратного порядка байтов, в котором первым идет старший бит. Шестнадцатеричные цифры в слове также находятся в обратном порядке.
Количество отображаемых 32-битных слов - это минимальное количество, необходимое для отображения всех битов битовой маски, в зависимости от размера битовой маски.
Примеры формата маски:
00000001 # just bit 0 set 40000000,00000000,00000000 # just bit 94 set 00000001,00000000,00000000 # just bit 64 set 000000ff,00000000 # bits 32-39 set 00000000,000E3862 # 1,5,6,11-13,17-19 set
Маска с битами 0, 1, 2, 4, 8, 16, 32 и 64 отображается как:
00000001,00000001,00010117
Первая «1» для бита 64, вторая для бита 32, третья для бита 16, четвертая для бита 8, пятая для бита 4 и «7» для битов 2, 1 и 0.
Почему существует несколько записей для "eth1" в форме "eth1-X"?
Потому что есть несколько очередей tx / rx. Эти очереди часто представляют собой хэш (локальный адрес, порт, удаленный адрес, порт) и некоторые другие вещи. Подавление множественных очередей может упростить создание более детерминированного приложения при условии, что у вас мало источников трафика. Или вы можете посмотреть алгоритм и избегать эфемерных портов, если это проще.
Вы используете ядро реального времени? Вы используете cgroups
или cpusets
изолировать ваше приложение? Если вы используете стандартное дистрибутивное ядро, вы оставляете на столе значительный выигрыш в задержке. Также я вижу 16 CPU-ядер. Это будет означать, что HyperThreading включен. Как узнать, привязаны ли вы к реальному ядру, а не к логическому?