NUMA
Коротко
NUMA (Non-Uniform Memory Access) - архитектура многопроцессорных систем, где доступ к “своей” памяти быстрее, чем к “чужой”.
Для сети критично: NIC подключен к конкретному CPU socket через PCIe. Если обрабатывать пакеты на “чужом” сокете - latency +50-100 ns, throughput -30-50%.
Архитектура NUMA
┌─────────────────────────────────────────────────────────────────────┐
│ NUMA Node 0 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ CPU 0-15 │ │ L3 Cache │ │ Local RAM │ │
│ │ │◄──►│ 32 MB │◄──►│ 128 GB │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
│ │ │ │
│ │ PCIe Root Complex │ │
│ │ │ │ │
│ │ ┌──────────┴──────────┐ │ │
│ │ │ NIC 100G │ │ │
│ │ │ (eth0, eth1) │ │ │
│ │ └─────────────────────┘ │ │
└─────────│─────────────────────────────────────────│─────────────────┘
│ │
│ QPI / UPI / Infinity Fabric │
│ (межсокетная связь) │
│ ~100 ns │
│ │
┌─────────│─────────────────────────────────────────│─────────────────┐
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ CPU 16-31 │ │ L3 Cache │ │ Remote RAM │ │
│ │ │◄──►│ 32 MB │◄──►│ 128 GB │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
│ NUMA Node 1 │
└─────────────────────────────────────────────────────────────────────┘Почему NUMA влияет на сеть
Правильно (локальный доступ):
Пакет → NIC → DMA в RAM (Node 0) → IRQ на CPU 0-15 → обработка
↓
Все в одном NUMA node
Latency: ~80 ns к RAMНеправильно (удаленный доступ):
Пакет → NIC → DMA в RAM (Node 0) → IRQ на CPU 16-31 (Node 1!)
↓
CPU идет за данными на Node 0
Latency: ~150 ns (QPI hop)
+ contention на interconnectВлияние на производительность
| Сценарий | Throughput | Latency |
|---|---|---|
| IRQ + App на локальном node | 100% | baseline |
| IRQ локально, App удаленно | 70-85% | +30-50 ns |
| IRQ удаленно, App локально | 60-80% | +50-70 ns |
| IRQ + App на удаленном node | 50-70% | +80-100 ns |
На 100G разница между правильной и неправильной конфигурацией: 40-100 Gbps vs 60-70 Gbps.
Диагностика
Посмотреть NUMA топологию:
| |
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 128000 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 128000 MB
node distances:
node 0 1
0: 10 21
1: 21 10Distance 10 = локальный доступ, 21 = удаленный (2.1x медленнее).
Посмотреть CPU и NUMA:
| |
NUMA node(s): 2
NUMA node0 CPU(s): 0-7,16-23
NUMA node1 CPU(s): 8-15,24-31Узнать NUMA node сетевой карты:
| |
0Значение -1 = не привязано (виртуалка или старое железо).
Визуальная топология (с PCIe устройствами):
| |
Проверить IRQ affinity:
| |
Проверить где работает приложение:
| |
Настройка
1. Отключить irqbalance (для ручного контроля):
| |
2. Привязать IRQ к локальному NUMA node:
| |
3. Запустить приложение на правильном NUMA node:
| |
4. Для nginx/haproxy - в systemd unit:
| |
5. Использовать set_irq_affinity скрипт от Intel/Mellanox:
| |
Автоматизация
Скрипт для настройки affinity:
| |
Команды
| |
Показать NUMA топологию: nodes, CPUs, память, distances.
| |
Запустить приложение с привязкой к NUMA node 0.
| |
Статистика аллокаций памяти по NUMA nodes.
| |
Статистика памяти конкретного процесса по nodes.
| |
NUMA node сетевой карты.
| |
Визуальная топология системы (CPU, cache, PCIe, NUMA).
| |
На каких CPU обрабатывается IRQ.
| |
Привязать IRQ к CPU 0-7.
Проверка
Убедиться что все правильно:
| |
Примеры
Типичная проблема:
| |
После настройки:
| |
Бенчмарк до/после (iperf3, 100G):
До (irqbalance, случайные CPU):
Bandwidth: 62 Gbps
CPU: 45% на node0, 35% на node1
После (IRQ + app на node0):
Bandwidth: 94 Gbps
CPU: 70% на node0, 5% на node1