Большие потоки трафика и управление прерываниями в Windows
Мне очень понравился топик про распределение нагрузки от прерываний сетевого адаптера по процессорам, поэтому я решил описать как это делается в Windows.
Disclaimer: судя по некоторым комментариям в предыдущих постах, мне стоит повторить то, с чего я начал первый пост: я не даю (и не могу давать) общеприменимых рецептов. Особенно это касается производительности, где мельчайшая неучтенная деталь может катастрофически повлиять на результат. Вернее рекомендацию то я даю: ТЕСТИРОВАНИЕ И АНАЛИЗ. Смысл моей писанины в том, чтобы дать людям как можно больше информации для анализа, ведь, чем больше понимаешь в том, как что либо работает, тем легче находить пути устранения боттлнеков.
Итак, масштабируемость пропускной способности сети. Потребуется Windows Server 2003 SP2+. Сетевая карта, поддерживающая Receive Side Scaling (можно с достаточной долей уверенности сказать, что подойдет любая серверная сетевая карта, выпущенная в последние 5 лет или любая вообще 1Gb+ NIC, хотя частенько можно увидеть RSS и на 100Mb). Устанавливаем Windows Server и драйвера на карту…
ВСЕ. Настройка завершена. RSS по умолчанию включен во всех версиях Windows, в которых он поддерживается.
Тестирование
Возьмем не особо новый Dell-овый сервер с двумя четырехядерными ксеонами: 
На борту две двухпортовые 1Gb сетевые карты и одна 10Gb, но я не нашел 10Gb свитча, так что завести не удалось — ну да ладно: 
Что интересно в этих картах, так это то, что несмотря на поддержку RSS в 8 очередей, они не поддерживают ни MSI-X ни даже MSI. Более того, из четырех доступных линий pin-based прерываний на каждый сетевой порт отведена только одна (соответственно никакими способами заставить прерывания приходить на разные процессоры уже нельзя — это аппаратное ограничение данной конфигурации). 10 гигабитка зарегистрировала на себя то ли 32 то ли 64 (на глаз) вектора прерываний, но ее использовать — не судьба. Сможет ли индусская поделка для запуска игр справиться с задачей? 
На всякий случай проверяем RSS (хотя если его не будет — будет заметно и так): 
Для начала выключим RSS (включал обратно я уже после тестирования, но том же окне) 
и запустим нагрузочный тест:
Полностью загружены два ядра, все остальные простаивают 
Сеть загружена на треть: 
50% одного процессора забито обработакой прерываний, еще 20% того же процессора — обработка DPC. Остальное — tcpip стек и приложение, которое отдает трафик. 
Включаем RSS (скриншот выше). Процессор: 
Сеть: 
Треть одного процессора забита прерываниями, но DPC отлично распараллелены. 
В общем, на данной конфигурации можно было бы отдавать порядка 3 гигабит (с одной сетевой карты) и только тогда мы бы встретили бутылочное горлышко.
На всякий случай, скажу, что у RSS есть менее известный родственник — Send Side Scaling. Если перед посылкой списка буферов выставить значение хеша, то прерывание после завершения посылки будет доставлено в соответствии с установленными indirection table-ами.
Вот здесь можно почитать про RSS, а здесь есть неплохая презентация в картинках поясняющая работу RSS. Если интересно, могу попробовать своими словами описать механизмы работы RSS, но как по мне — лучше читать первоисточники.
TCP Offload Engine
Если нечто подобное RSS в Linux вот-вот появится (не нашел никаких упоминаний о поддержке нормального аппаратного RSS в Linux: кто знает — дайте ссылку — проапдейчу пост). То с TOE в Linux все официально сложно. Патч от Chelsio (один из производителей high-end сетевых карт), реализующий поддержку TOE, был отклонен, а вместо этого начались какие то совершенно идиотские отмазки (при прочтении стоит иметь в виду, что BSD и Windows имеют нормальную поддержку TOE уже много лет).
Итак, что же это такое? TOE — это полная реализация TCPIP на аппаратном уровне: с подтверждением доставки, ретрансмитами при ошибках, контролем окна и пр.: сетевая карта по DMA прямо из памяти берет данные, режет на пакеты, присоединяет хедеры, а рапортует (при помощи прерываний) только в самых крайних случаях.
По умолчанию TOE стоит в automatic режиме. Смотреть Chimney Offload State: 
Скриншот снимался во время активного тестирования, но в статистике видно, что ни одного «выгруженного» в сетевую карту соединения нет (о причинах позже). Включем принудительно (и через некоторое время запрашиваем статистику): 
А вот и причина: в данную сетевую карту можно выгрузить только 1024 соединения (но реально система смогла выгрузить 1022). Довольно дорогой ресурс, чтоб можно было выгружать все подряд. Система эвристически пытается обнаруживать соединения (get/put больших файлов по http, пересылка файлового контента на файл-серверах и т.п.), которые проживут долго и выгружает в первую очередь их.
Но все же глянем, что получилось. Процессор разгрузился втрое: 
Очень сильно уменьшилось количество (и время проводимое в) как ISR так и DPC: 
Максимальное число очередей RSS — что это?
Максимальное число очередей RSS — настройка, позволяющая выставить обрабатываемое количеств потоков RNIC-адаптера.
Данная настройка определяет, сколько потоков можно использовать RNIC-адаптеру. Какое именно количество — можно узнать в характеристиках адаптера. Если выставит больше, чем нужно — может быть снижение сетевой производительности. Также были случаи некорректно работы опции при использовании неактуальных драйверов.

RNIC (RDMA Network Interface Controller) — сетевой адаптер с аппаратным ускорением технологии прямого доступа к памяти RDMA. Это удаленный доступ к оперативной памяти, который имеет сетевая карта. Данные технологии используются в серверных конфигурациях, на обычных домашних компьютерах эти настройки нет смысла использовать. Да и вряд ли они будут на обычных сетевых картах типа Realtek.
Настройка числа обработчиков RSS
Для повышения общей производительности компьютера администраторам следует задать количество процессоров приема-получения (на стороне).
Параллельные вызовы отложенных процедур (DPC), выполняющиеся на нескольких процессорах, обеспечивают распределенную обработку приема и устраняют узкие места ЦП (например, в высокоскоростных сетевых картах). Однако несколько DPC создают дополнительные издержки. Издержки на обработку прерываний и DPC увеличиваются по мере использования процессоров для RSS. Таким образом, когда RSS активен, общее использование ЦП во всех процессорах увеличивается. Администратор должен выбрать количество процессоров, используемых для RSS, чтобы избежать ситуации, когда использование RSS оставляет меньше вычислительной мощности для использования приложениями и не повышает пропускную способность сети.
начиная с Windows 8 и Windows Server 2012 администраторы могут управлять многими аспектами сетевых адаптеров с помощью командлетов PowerShell. Непосредственное редактирование реестра теперь не рекомендуется.
Командлет PowerShell для настройки числа ЦП RSS — Set-нетадаптеррсс.
Основное различие между использованием Set-нетадаптеррсс и ключевым словом реестра макснумрсскпус заключается в том, что командлеты PowerShell работают с каждым сетевым адаптером, а макснумрсскпус — глобальным. Это означает, что оно применяется ко всем сетевым адаптерам. Как правило, рекомендуется работать с каждым сетевым адаптером отдельно, так как он обеспечивает большую гибкость, детализацию и понятность при предоставлении каждому сетевому адаптеру собственной конфигурации. Однако администраторы по-прежнему могут использовать глобальный ключ макснумрсскпус , если они хотели бы применить конфигурацию ко всем текущим и всем будущим сетевым адаптерам в то же время.
Полный список командлетов сетевого адаптера см. в разделе командлеты сетевого адаптера в Windows PowerShell.
в Microsoft Windows Server 2003 с масштабируемым сетевым пакетом администраторы могут установить максимальное количество цп в HKEY_LOCAL_MACHINE\\SYSTEM\CurrentControlSet\Services\Tcpip\Parametersс помощью ключевого слова реестра макснумрсскпус . Значение макснумрсскпус имеет тип DWORD и, если он отсутствует, NDIS использует значение по умолчанию 4.
в Windows Server 2008 администраторы могут задать максимальное число цп RSS с помощью ключевого слова реестра макснумрсскпус в HKEY_LOCAL_MACHINE\\SYSTEM\CurrentControlSet\Services\Ndis\Parameters. Значение макснумрсскпус имеет тип DWORD и, если он отсутствует, NDIS использует значение по умолчанию 4. это ключевое слово реестра также применимо к более поздним версиям Windows Server.
Чтобы избежать сложных случаев (и нереалистичных случаев, которые не реализованы в фактическом оборудовании), где число доступных очередей получения оборудования меньше числа ЦП RSS, администраторы не должны присвоить макснумрсскпус значение больше 16.
Фактическое число ЦП, используемых для RSS, также ограничивается общим числом процессоров, которые остаются после настройки базового процессора RSS. Например, если администратор устанавливает максимальное количество процессоров RSS на компьютере с четырехъядерным компьютером до 6, в стеке драйверов сети используется не более 4 ЦП для RSS. Если администратор также устанавливает для базового процессора RSS значение 1, стек драйверов сети использует не более 3 ЦП (номера ЦП 1, 2 и 3).
Число ЦП, используемых компьютером для RSS, является статическим и не изменяется во время выполнения. Поэтому для вступления в силу всех изменений в значении реестра макснумрсскпус требуется перезагрузка.