На двухсокетном сервере память физически разделена между процессорами: у каждого сокета свой контроллер и свой банк DRAM. Процесс на CPU первого сокета, чьи страницы памяти выделены рядом со вторым, платит лишней латентностью на каждое обращение — оно уходит через межпроцессорную шину вместо локальной. Это и есть NUMA (Non-Uniform Memory Access), и для баз данных или числодробилок разница заметна прямо в задержках запросов.

Посмотреть топологию — сколько узлов видит система и какие у них расстояния друг от друга:

numactl --hardware

Чем больше число в таблице distances между узлами, тем дороже туда лазить за памятью — переход к соседнему сокету обычно в разы медленнее локального доступа.

numactl умеет не только показывать, но и привязывать. --cpunodebind ограничивает процесс ядрами конкретного узла, --membind заставляет брать память строго оттуда же, без права на запасной узел при нехватке места:

numactl --cpunodebind=0 --membind=0 ./my_service

Для PostgreSQL или 1C-сервера на многосокетной машине это обычная практика — закрепить процесс за одним NUMA-узлом вместо того, чтобы планировщик ОС мигрировал его между сокетами, а память оставалась россыпью по всем узлам сразу.

#linux #performance