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

ethernet smp_affinity vs / proc / interrupts vs / sys / class / net / ethX / device

Моя цель - настроить наши серверы 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 включен. Как узнать, привязаны ли вы к реальному ядру, а не к логическому?