На двухсокетном сервере память физически разделена между процессорами: у каждого сокета свой контроллер и свой банк 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
