Как распределяются пакеты из очередей сетевого интерфейса в ЦП, а затем в потоки для обработки? Что необходимо учитывать, когда дело доходит до хеширования пакетов по очередям, аппаратных прерываний по сравнению с softirq, локальности ЦП / памяти / приложений / потоков и многопоточности по сравнению с многопроцессорными демонами, чтобы избежать как можно большего перепланирования / копирования пакетов?
У меня есть многопоточный сетевой демон (например, Unbound resolver), работающий с 16 собственными потоками на Debian amd64 с Linux 2.6.32 (да, старый), поэтому нагрузка приложения распределяется на 16 процессоров. Сетевая карта - это bnx2 (BCM5709S) с поддержкой 8 очередей MSI-X rx / tx. IRQ каждой очереди назначается отдельному процессору путем статического сопоставления привязки прерывания в / proc / irq / n / smp_affinity (irqbalance никогда не помогал), а тип хеширования очереди (тип RSS) является типом по умолчанию (IP src + dst , TCP sport + dport) с ключом хеширования по умолчанию.
Все это помогает распределить нагрузку, но не равномерно: обычно есть один поток приложения, который выполняет в два раза больше работы (= запросов в секунду), чем другие потоки, и скорость softtirq одного процессора (вероятно, того, который обрабатывает этот конкретный поток) в два раза выше, чем у другого. ЦП.
В процессорах включена гиперпоточность, но я еще ничего не сделал для распределения нагрузки по «реальным» ядрам (что мне действительно нужно).
Linux поставляется с довольно обширным документ сетевого масштабирования, но мне не хватает пробелов:
В документе говорится о конфигурации RSS:
Типичная конфигурация RSS будет иметь одну очередь приема для каждого ЦП, если устройство поддерживает достаточное количество очередей, или, в противном случае, по крайней мере, по одной для каждого домена памяти, где домен памяти - это набор ЦП, которые совместно используют определенный уровень памяти (L1, L2 , Узел NUMA и т. Д.).
В: Как определить конфигурацию домена ЦП / кеш / память для моего сервера?
Информация об управлении потоком приема (RFS), кажется, отвечает на некоторые из моих вопросов о передаче пакета нужному процессору / потоку:
Цель RFS - увеличить скорость обращения к кэшу данных, направляя обработку пакетов ядром в ЦП, где выполняется поток приложения, потребляющий пакет.
В: В случае разрешения DNS обычно есть один пакет запроса и один пакет ответа. С многопоточным демоном будет ли только один поток запускать bind () + recvfrom () и, таким образом, все равно должен обрабатывать все новые входящие пакеты, прежде чем планировать работу для других потоков? Выиграет ли этот конкретный вариант использования от разветвленной операции (один процесс на процессор)?
В: Будет ли управление потоком лучше всего применяться к многопоточному демону TCP?
В: Как вы определите, использовать ли многопоточную или многопроцессорную работу? Очевидно, есть общая память и структуры данных, конкуренция за ресурсы и т. Д., Но я думаю о потоке пакетов и прослушивателях приложений.
В: Без управления потоком приема или с простыми службами UDP может ли пакет прибыть на «неправильный» ЦП и, следовательно, будет каким-то образом перенесен на «правильный» ЦП? Будет ли это вызывать софт NET_RX?
В: Есть ли NET_RX softirq между очередью сетевой карты и ЦП? Есть ли еще что-то между ЦП и слушающим потоком / процессом? Может ли быть еще один, если получающий поток планирует пакет для рабочего потока, если это даже возможно?
Жаль, что у Бена Хатчингса нет видео или дополнительных деталей. netconf 2011 обсуждение, где он освещает большинство из этих вещей. Слайды несколько краткие.
Я попытаюсь обновить ядро до более новой версии с пригодной для использования версией perf, а затем проверю, чем заняты процессоры, возможно, обнаружив, что это за высоконагруженный процессор по сравнению с другими.
Примечание: я не пытаюсь решить здесь конкретную проблему, скорее я пытаюсь понять, как эти вещи работают в ядре Linux. Я также знаю о различных вариантах объединения прерываний.