Недавно довелось разбираться с проблемой производительности сетевой подсистемы Linux. Как и предполагалось проблема была связана с обработкой сетевых прерываний. Однако выяснилось что термин MSI-X знаком не всем и далеко не все понимают преимущества этой технологии и покупают карты где она не поддерживается.
Более того, при беглом осмотре выяснилось что далеко не все вендоры продают адаптеры с поддержкой MSI-X.
Но начну я как всегда издалека.
Обработка hardware прерываний всегда была “дорогой” операцией. “Дороговизна” связана как с большим количеством прерываний, так и со сложностями по распределению их обработки.
Проблема с количеством прерываний в Linux была частично решена с появлением NAPI: вместо прерывания по каждому событию, теперь драйвер сетевой карты самостоятельно забирает пришедшие пакеты из очереди карточки.Полноценная же возможность по распределению прерываний по cpu появилась лишь с приходом PCI 3.0 и MSI-X.Но сначала немного теории.
Обработка PCI прерываний
Изначально PCI шина была ограничена 4 линиями, выделенными под прерывания. Теоретически один PCI адаптер может использовать все 4 прерывания, но так-как эти прерывания являются общими для всех карт, то большинство PCI адаптеров использую лишь 1 прерывание.
Из-за того что PCI прерывания были общими для всех устройств на шине, для корректной обработки прерывания ОС была вынужденна запускать все обработчики данного прерывания.
Если же PCI устройство писало в память, то возникала проблема синхронизации и обработчик прерывания был вынужден проверять что данные действительно записаны в память. Это было необходимо т.к. прерывание посылалось по выделенным линиям и могло быть отправлено одновременно с операцией записи а значит и “прийти” на процессор до того как данные реально будут записаны в память. Проблема синхронизации решалась на уровне драйверов: необходимо считать регистр, тем самым убедиться что операция записи завершена. Это добавляло накладных расходов для обработчика прерываний и не делало его более производительным.
Все эти проблемы был призван решить MSI.
MSI
Если ранее за каждым устройством закреплялся свой номер запроса на прерывание (IRQ), то прерывание в случае MSI это запись по заранее определенному адресу. Благодаря этому отпадает необходимость в выделенных линиях для обработки прерываний и упрощается схема самого адаптера. Кроме того решается проблема с синхронизацией т.к. операция записи в память и прерывание теперь используют общий канал и более не могут прийти на процессор одновременно.
MSI позволяет использовать десятки прерываний. Точнее до 32. Однако более 16 прерываний использовались крайне редко.
MSI-X
В PCI 3.0 появилось расширение MSI : MSI-X позволило увеличить кол-во прерываний от одного устройства до 2048. Правда использование более 64 я не встречал. Но что более важно, MSI-X использует различные адреса записи для каждого прерывания, что позволило назначить обработку отдельный прерываний на определенный процессор.
APIC и распределение прерываний между CPU
APIC (Advanced Programmable Interrupt Controller) отвечает за распределение прерываний по процессорам. APIC предусматривает несколько различных политик распределения прерываний. Так первоначально все прерывания обрабатывались одним ( нулевым ) ядром.
За распределение прерываний по CPU отвечает чип IO-APIC. Этот чип может работать в 2 режимах :
fixed/physical mode: прерывания от каждого конкретного устройства обрабатываются конкретным CPU
logical mode: прерывания одного устройства могут обрабатываться несколькими CPU.
Применение logical mode в большинстве случаев не оправдано т.к. возникают проблемы cache miss’ов в случае работы с одной сущностью несколькими CPU ( например обработке прерываний несколькими CPU для одной tcp сессии ).
Попробую описать эту проблему детальнее. Итак у вас прерывания разбрасываются round-robin по нескольким CPU. Когда приходит первый пакет tcp сессии и генерируется прерывание, то оно обрабатывается процессором X. Второе прерывание о пакете, в рамках того же tcp соединения попало на процессор Y. Так как данных о данной сессии до этого на процессоре Y не было то никаких данных о ней CPU кеше нет Имеем cache miss на процессоре Y. При этом данные были в кеше процессора X и если бы прерывание попало на процессор X то обо было бы обработано быстрее. Теперь же данные о этой tcp сессии удаляются из кеша процессора X для обеспечения когерентности кешей. Однако следующее прерывание о новом пакете в рамках этой же tcp сессии снова попадает на процессор X и мы снова получаем cache miss…
Получается что с одной стороны выгодно распределять прерывания по всем CPU, чтобы CPU не было узким место и была равномерная загрузка CPU.
С другой стороны распределение прерываний по разным CPU безо всякой логики повышает кол-во cache miss. А это “дорогая” операция также оказывает влияние на производительность.
IO-APIC и MSI
На самом деле через IO-APIC будут распределяться либо прерывания “старого” типа (INT), либо MSI/MSI-X прерывания, для устройств, драйвера которых не реализовали поддержку MSI/MSI-X.
Как я описал выше MSI/MSI-X генерирует прерывания, посылая операцию записи с определенным адресом. Соответственно если драйвер не поддерживает MSI/MSI-X то будет использоваться некий стандартный адрес и прерывания будут попадать на IO-APIC и далее уже распределяться по LAPIC ( Local APIC ) разных CPU.
В случае же если в драйвере реализована поддержка MSI/MSI-X то при инициализации адрес может быть изменен, а значит прерывания будут попадать на определенный CPU в обход IO-APIC.
Так в чем же плюс MSI-X?
Помните предыдущий пример про tcp сессию,А что если бы сетевая карта “знала” о tcp сессиях и генерировала бы прерывания для того CPU, который и занимается обработкой данной tcp сессии? Это позволило бы решить и проблему с распределением прерываний по нескольким CPU при этом обеспечивая локальность обработки пакетов определенного типа.
Именно этого и позволяет добиться MSI-X.
Теперь о командах. lspci -t
показывает список PCI устройств и мостов.
После чего в файле /sys/bus/pci/devices/*/msi_bus
можно увидеть включена ли поддержка MSI: 1 – включена 0 – выключена.
Распределение прерываний по ядрам CPU вы можете посмотреть в файле /proc/interrupts . Там же можно увидеть используется ли IO-APIC для распределения прерываний, или же прерывания идут напрямую через MSI.
Для каждого прерывания есть директория в /proc/irq/ . В файле smp_affinity находится bitmap, который определяет каким ядром будет обрабатываться это прерывание. Меняя этот bitmap мы можем менять привязку прерываний к ядрам процессора.
О том как обработка MSI и MSI-X прерываний реализована в Solaris отлично написано здесь : в блоге Saurabh Mishra
и частично в блоге Charlie Chen здесь и здесь
Hello dear friend, I would like to offer placement of your link (or links) on different platforms of the internet such as: forums, blogs, comments and much more. . .
Increase your Visibility Boost Your Seo Rank – Get Organic Traffic From Google. Ranking in Google isn’t hard. All you need is a healthy number of backlinks from referring domains that have authority and trust in Google’s eyes.
This Backlinks Service Benefits:
1. Easily get Google rankings
2. Get a lot of traffic from Google
3. You can earn from the website in different ways
4. Increase Domain Authority (DA)
Quality guaranteed !
PRICE – 10$
WebSite – http://traffic-for-your.site/
Hello,
Club-Music download https://0daymusic.org MP3, FLAC, LIVESETS, Music Videos.
Team 0day
Very excellent information can be found on weblog.Raise range
I’m really impressed with your writing abilities as well as with the format on your weblog. Is that this a paid theme or did you customize it your self? Either way stay up the nice quality writing, it is rare to peer a great weblog like this one these days!