...

Правильный анализ статистики NUMA в Linux

Linux NUMA Статистика показывает мне, насколько эффективно процессы хранят данные локально и где удаленные запросы приводят к увеличению задержек. Я объясняю, как целенаправленно анализировать эти цифры, оценивать тенденции во времени и на их основе определять четкие меры по оптимизации для Производительность производные.

Центральные пункты

  • Понимание счетчиков: numa_hit, numa_miss, numa_foreign, local_node, other_node, interleave_hit
  • Оценить контекст: профиль нагрузки, топология, тип рабочей нагрузки
  • Оценка тенденций: «До/после» и по интервалам
  • Проверка процессов: для всей системы vs. для каждого процесса
  • Применить настройку: Affinity, Policies, Размещение

Что на самом деле показывают статистические данные NUMA

Я рассматриваю показатели NUMA как карту для Место хранения и каналы передачи данных. Высокий numa_hit означает, что выделения памяти были размещены на нужном узле. Напротив, numa_miss указывает на то, что ядру пришлось переключиться на другой узел. Счетчик numa_foreign показывает соответствующее значение на целевом узле и дополняет общую картину. С помощью local_node и other_node я могу определить, оставались ли обращения локальными или использовали удалённую память.

Эти показатели никогда не следует интерпретировать в отрыве от контекста, поскольку Рабочие нагрузки реагируют по-разному. Короткие процессы в отдельных случаях приводят к промахам, не оказывая заметного влияния на общую производительность. В свою очередь, политики чередования (Interleave-Policies) намеренно распределяют ресурсы, что приводит к росту показателя interleave_hit. Поэтому я всегда проверяю заданную политику и текущую нагрузку. Только после этого я решаю, требует ли данное значение принятия мер или соответствует замыслу системы.

Для меня основная идея заключается в следующем: Счётчик предоставляют сигналы, а не выводы. Я ищу закономерности во времени, а не отдельные цифры. Так я определяю, приводит ли изменение в системе к сдвигу локальности. Только на основе этой картины тенденций я оцениваю, следует ли переносить процессы, корректировать политики или устанавливать привязки к процессорам. Поэтому каждый анализ NUMA начинается с четко сформулированной задачи и повторяемых точек измерения.

Интерпретация показаний счетчика ядер в контексте

Я всегда сравниваю numa_hit и сравниваю numa_miss между собой, вместо того чтобы оценивать абсолютные значения. Если количество промахов растёт, я параллельно проверяю динамику показателя numa_foreign на потенциальных целевых узлах. Если оба показателя совпадают, это указывает на реальный перенос, а не на простой артефакт чтения. local_node и other_node дополняют эту картину данными о фактических обращениях к памяти. Так я могу определить, началась ли аллокация локально, но впоследствии операция читала данные из более удалённой памяти.

Один высокий other_node Меня не беспокоит, если рабочая нагрузка распределяется сознательно. Зато веб-серверы с большим количеством рабочих процессов выигрывают от последовательной локальности. Поэтому я анализирую процессы, а не только общую картину. Как только отдельные службы начинают выбиваться из общего ряда, я пересматриваю их размещение. Только когда по всей системе начинают расти показатели сбоев, я ищу причины в топологии или загрузке.

Сравнения во времени: эффективная процедура измерения

Я снимаю показания счетчиков в начале и в конце Заключительная фаза и вычисляю разницу. Отдельные значения затуманивают картину, а разницы показывают динамику. Повторные интервалы, например, от 30 до 60 секунд, часто бывают достаточными для выявления тенденций. После развертываний, обновлений ядра или изменений аппаратного обеспечения я снова сравниваю те же интервалы. Если в этот раз наблюдается больше промахов или происходит сдвиг local_node, это означает, что произошло реальное изменение.

Такие временные ряды охватывают Ошибка размещения быстрее, чем моментальные снимки. Я сопоставляю эти линии с загрузкой ЦП, сменой контекста и загрузкой памяти на каждый узел. Таким образом я вижу, приводят ли перегрузки оперативной памяти узла к отклонениям в поведении. Или же новые процессы нарушают баланс узлов. Само соотношение «попаданий» и «промахов» я всегда представляю в виде графика, а не отдельного числа.

Проверить всю систему, затем детально изучить процессы

Я начну с общего обзора numastat и только после этого проверяю отдельные процессы. Такая последовательность позволяет сэкономить время, поскольку многие эффекты становятся заметны на глобальном уровне. Для просмотра процессов я использую вывод данных по конкретному процессу, чтобы выделить подозрительные службы. Как только кандидаты определены, я настраиваю Размещение о загрузке процессора и памяти. Практические рекомендации по этому вопросу собраны в статье, посвящённой Аффинность процессора и памяти.

Именно в случае с Java-сервисами, PHP-FPM или базами данных зачастую достаточно простой Affinity, чтобы значительно сократить количество сбоев. Оркестрация контейнеров часто маскирует эти проблемы, поскольку планировщики распределяют задачи без учета NUMA. Поэтому я контролирую распределение узлов для каждого пода или виртуальной машины. Если наборы процессоров и выделение ОЗУ совпадают, показатель local_node заметно возрастает. Некоторые проблемы решаются, как только процесс запускается вблизи необходимого набора данных.

Обзор счетчиков NUMA (таблица)

При оценке новой системы я составляю следующую таблицу, чтобы учесть каждую Ключевая фигура быстро сориентироваться. В ней указаны значение, типичная интерпретация и возможные меры. Я воспринимаю её не как жесткую схему, а как контрольный список. Решающим фактором остаётся сопоставление с профилем нагрузки и топологией сервера. Только с учётом этого контекста я могу принять обоснованное решение.

Счётчик Значение интерпретация Подход
numa_hit Распределение в нужном узле Высокое значение — это хорошо Сохранить позицию
numa_miss Распределение перешло на другие узлы Повышенный риск возникновения задержек Проверить Affinity/Policy
numa_foreign Внешнее распределение ресурсов на этом узле Аналог numa_miss Анализ целевых узлов
local_node Обращения к локальному хранилищу Чем выше, тем дешевле Процесс, расположенный ближе к оперативной памяти
other_node Обращения к удаленному хранилищу Просто вызывает опасения, хотя и непреднамеренно Проверить топологию/нагрузку
interleave_hit Попадания при чередовании Ожидаемое значение для Interleave‑Policy Оценить равномерность

С помощью этого Обзор я быстрее принимаю решение о том, когда следует вмешаться. Рост показателя numa_miss без объяснимых изменений вызывает анализ причин. Если показатель interleave_hit остаётся высоким, я проверяю, не активирована ли политика намеренно. Если показатель other_node растёт без увеличения нагрузки, я проверяю, не вытесняют ли другие рабочие нагрузки. Таким образом, таблица становится отправной точкой для целенаправленных действий.

Понимание и использование топологии NUMA

Прежде чем настраивать, я проверяю Топология сервера: сокеты, ядра, каналы памяти, пути задержки. Если процесс работает на сокете 0, но его рабочие наборы находятся на сокете 1, время доступа увеличивается. Это снижает пропускную способность и приводит к колебаниям времени отклика. Службы, особенно требовательные к памяти, чувствительны к любому ненужному удалению. Поэтому я размещаю процессы с интенсивным использованием данных на узлах с достаточным объёмом свободной оперативной памяти.

Асимметричные Подключения усиливают эффекты, например, когда узел использует меньшее количество каналов. В таких случаях я целенаправленно перемещаю кешированный набор данных, вместо того чтобы распределять процесс. Хосты виртуальных машин и контейнеров я настраиваю таким образом, чтобы каждый экземпляр получал стабильную привязку к узлу. Таким образом я сокращаю удалённый трафик данных, не ограничивая квоты. Физические ограничения машины задают рамки, и я их соблюдаю.

Правильное понимание принципов чередования и балансировки

Политики чередования целенаправленно распределяют память по узлам, чтобы Пропускная способность порост на каждый процесс или снижение количества «горячих точек». В этой конфигурации высокие значения interleave_hit считаются желательными. В таком случае я в первую очередь проверяю равномерность, а не абсолютную локальность. AutoNUMA или NUMA-балансировка могут помочь, но не во всех случаях.

Я решаю в зависимости от ситуации, следует ли использовать автоматический Балансировка остается активным. Для стабильных, долго работающих сервисов я предпочитаю использовать фиксированные привязки. При изменяющихся нагрузках AutoNUMA может эффективно реагировать на изменения. Хороший обзор преимуществ и рисков приведен в статье Балансировка NUMA. Только после того, как цель и рамки станут ясными, я выбираю подходящий режим.

Типы рабочих нагрузок: базы данных, виртуальные машины, веб-сервисы

Базы данных чувствительны к Латентность между ЦП и оперативной памятью. Поэтому я размещаю экземпляр, буферный кэш и активные шарды на одном узле. Виртуальные машины выигрывают от чётко определённых наборов процессоров в сочетании с оперативной памятью узла, что позволяет гостевым операционным системам видеть согласованные пути доступа. Веб-сервисы с большим количеством рабочих процессов демонстрируют наилучшую производительность, когда группы рабочих процессов остаются привязанными к одному узлу. В качестве стратегии хранения я использую, в зависимости от конкретного случая, целенаправленные Политики управления памятью NUMA.

А вот аналитические задачи и масштабные сканирования я выполняю частично распределяется . В данном случае чередование часто обеспечивает более высокую пропускную способность, чем жесткая локальность. Важно объективно оценивать модели ввода-вывода рабочей нагрузки. Запись доминирует иначе, чем чтение, а произвольные обращения — иначе, чем последовательные. Я выбираю политику, которая соответствует модели доступа, а не ту, которая хорошо звучит в учебнике.

Практическая процедура измерения и инструменты

Для начала мне достаточно numastat и обзор процесса. Я фиксирую показания счетчиков с указанием даты, PID и индикаторов нагрузки. При этом важно проводить измерения в одинаковые временные интервалы. Так можно чётко отобразить различия «до» и «после». В рабочих интервалах я записываю значения дельта и соотношу их со сроками выпуска.

При наличии заметных Услуги Кроме того, я проверяю привязку к ЦП и видимость узлов с помощью таких инструментов, как lscpu, numactl и perf для отслеживания удаленной нагрузки. Я документирую выбранную политику для каждого цикла измерений. После внесения изменений я провожу повторные измерения. Только когда линии тренда стабилизируются, я считаю эффект достигнутым. Слепое переключение легко приводит к кажущимся улучшениям.

Как избежать распространенных ошибок в интерпретации

Высокий interleave_hit Это не является ошибкой, если интерлейв включен намеренно. Точно так же единичный сбой при длительном времени выполнения можно считать пренебрежимо малым. Я всегда проверяю плотность и распределение по всему интервалу, а не только пиковые значения. Некоторые воспринимают показатель other_node как однозначно негативный и упускают из виду характер рабочей нагрузки. Поэтому я сначала изучаю проектные цели, а уже потом оцениваю цифры.

Еще одно заблуждение: Общий вид Хорошо, значит, всё в порядке. Часто аномалии скрываются лишь в некоторых PID. Или планировщик контейнеров распределяет поды по разным узлам, хотя было бы целесообразно сгруппировать их локально. Такие явления я замечаю только тогда, когда провожу измерения по каждому процессу. Без такой детализации анализ остаётся неполным.

Эффективные шаги по тюнингу

Я начинаю с Размещение: Процессы на узлах, где данные находятся или должны находиться. Затем я настраиваю CPU-аффинность, чтобы потоки не перескакивали с одного сокеля на другой. Далее следует привязка к памяти, чтобы ядро выделяло память в нужном месте. Для переменных нагрузок я проверяю политики и, если они подходят, использую AutoNUMA.

Затем я позабочусь о Последовательность В рамках жизненного цикла: перезапуски, развертывания и масштабирования не должны произвольно изменять привязки узлов. Я документирую привязки в коде, чтобы они оставались воспроизводимыми. Затем я повторно провожу измерения, оцениваю отклонения и принимаю решение о тонкой настройке. Каждое изменение должно подкрепляться четкими результатами измерений.

Практический пример: от провала к успеху

Предположим, что одна База данных при нагрузке показывает большее значение numa_miss и рост other_node. Задержка запросов колеблется сильнее. Сначала я проверяю привязку процессов и обнаруживаю, что после развертывания сервис работает на узле A, однако кэш был выделен на узле B. После фиксированной привязки ЦП и памяти к узлу B соотношение меняется: показатель numa_hit растёт, а количество промахов снижается. Время отклика становится более стабильным, а нагрузка на ЦП слегка снижается, поскольку исчезают удалённые запросы.

Параллельно с этим я проверяю Политика. Функция Interleave была случайно включена и распределяла выделения памяти. После перехода на приоритетный узел кэш остаётся закрытым и локальным. По результатам часового измерения разницы подтверждают улучшение. Только тогда я считаю настройку успешной. Без этой перепроверки моментальный снимок мог бы ввести в заблуждение.

Показатели и ориентировочные значения для практического применения

При принятии решений я использую надежные Коэффициенты вместо отдельных исходных значений. Для каждого процесса я рассчитываю коэффициент распределения local_alloc = numa_hit / (numa_hit + numa_miss). Кроме того, я анализирую Коэффициент доступа local_access = local_node / (local_node + other_node). Эти два показателя вместе показывают, остается ли память локальной даже после выделения. В качестве приблизительных ориентиров я руководствуюсь следующим: для сервисов, чувствительных к задержкам, я стремлюсь к тому, чтобы количество удаленных обращений не превышало 5–10 %. При аналитических нагрузках, требующих высокой пропускной способности, я допускаю 20–30 %, при условии, что пропускная способность растёт. Решающим фактором является Стабильность во времени. Я предпочитаю показатель, который остаётся стабильным под нагрузкой, чем кратковременный пик с идеальными значениями. Я фиксирую эти целевые диапазоны для каждого обслуживания, чтобы впоследствии можно было чётко соотнести результаты измерений.

Cgroups, контейнеры и «ловушки» планировщика

В контейнерных средах я сначала проверяю cpuset‑Привязка: наборы процессоров и cpuset.mems должны охватывать одно и то же пространство узлов, иначе неизбежно возникнут сбои. Я слежу за тем, чтобы поды с фиксированными запросами на ЦП не распределялись между несколькими узлами NUMA, а также чтобы планировщик не распределял рабочие процессы одного и того же приложения по разным узлам. Для типов «Burst» я ограничиваю максимальное количество потоков на каждый под таким образом, чтобы они оставались в пределах одного узла. Я документирую Домен NUMA на каждое развертывание и требую согласованных реплик (одна рабочая группа на каждый узел, а не половины групп, распределенных по двум узлам). Если я слишком скупо рассчитываю размер памяти на каждый pod, я создаю себе ненужное давление: небольшой запас на каждый узел не даст ядру слишком рано переключаться на сторонние узлы. Если контейнеры часто перезапускаются, я слежу за детерминированной привязкой, чтобы Холодный старт не случайно получили худшее местоположение.

Выравнивание виртуальных машин и vNUMA с соблюдением согласованности

Что касается виртуальных машин, то я обращаю внимание на vNUMA: Виртуальная топология должна соответствовать физической. Я распределяю виртуальные процессоры (vCPU) таким образом, чтобы каждый узел vNUMA приходился ровно на один физический узел NUMA. На стороне хоста я привязываю потоки QEMU/гипервизора к этому домену и обеспечиваю, чтобы выделенная оперативная память полностью предоставлялась из этого узла. Воздушные шары Что касается overcommit, я с осторожностью допускаю его использование для виртуальных машин, для которых задержка имеет критическое значение; агрессивное использование ballooning может вытеснить горячие наборы из узла и привести к резкому увеличению количества удаленных обращений. При «живой» миграции я после перемещения повторно проверяю привязки — в некоторых средах при этом теряются точно настроенные привязки к ЦП и памяти. Только после того, как выравнивание по vNUMA налажено, я оцениваю numastat в масштабе всей системы: в противном случае я устраняю симптомы, а не причину.

THP, Hugepages и миграция страниц

Прозрачные огромные страницы (THP) могут как помочь, так и помешать. Более крупные страницы уменьшают количество промахов TLB и повышают пропускную способность, однако если ядро начинает использовать Hugepages слишком поздно рушится или перенесены, могут возникнуть несоответствующие Расстояния между пунктами возникают. Я придерживаюсь двух правил: во-первых, Политика Чётко определить (например, предпочтительный узел) и, по возможности, с самого начала выделять большие объёмы памяти локально. Во-вторых, для рабочих нагрузок с фиксированными большими кэшами я, по возможности, использую статические Hugepages (hugetlb), которые я явно резервирую на одном узле. Это снижает фрагментацию и компенсационные перемещения. Если я вижу по временным рядам, что после длительного времени работы other_node— по мере роста доли я проверяю, не Перенос страниц или происходит компактизация, и соответствуют ли настройки THP данному сценарию. Для меня важно: не отключать и не включать их глобально — я принимаю решение для каждой службы отдельно и оцениваю влияние на локальность и задержку.

Как правильно интерпретировать показатели «Reclaim», «Swap» и «Memory‑Pressure»

Если показатели растут без заметного изменения позиции, я ищу давление в аккумуляторе на узел. Заполненные узлы вынуждают ядро выполнять реклайминг и компактизацию, что частично вызвано kswapd на другом узле — это приводит к побочным эффектам в работе счетчиков. Я проверяю для каждого узла объем свободной памяти и загрузку кэша страниц. Включенная Обмен может вытеснить «горячие» наборы и привести к резкому росту задержек; для особо чувствительных сервисов я отключаю подкачку или строго ограничиваю её. В логах и отчётах perf я ищу пики реклайма во время пиковых нагрузок. Цель — обеспечить достаточное количество свободного, местные Сохранять объем ОЗУ на целевом узле, чтобы предотвратить смещение выделений памяти. Если для этого потребуется уменьшить размер кэшей, я отдаю приоритет рабочему набору службы перед общим страничным кэшем.

Практические команды и анализ результатов

Для просмотра процесса я использую numastat -p и добавьте: cat /proc//numa_maps, чтобы просмотреть распределение ресурсов по областям (анонимное, с файловой поддержкой) и по узлам. numactl --hardware предоставляет мне матрицы задержек и размеры узлов, lscpu --extended отображает сопоставление ЦП с узлами. Для доступа к памяти с упором на удаленные пути я устанавливаю перф. пам. для проверки моделей нагрузки. Я собираю данные «Дельта» воспроизводимым образом, например:

Процедура измерения

  • t0: сохранить numastat (общий) и numastat -p для Top-PID
  • 30–60 с работы с нагрузкой, идентичная фаза нагрузки
  • t1: повторно прочитать numastat, вычислить дельты для каждого счетчика
  • Регистрация значений параллельных процессоров, смены контекста и узлов

Затем я рассчитываю Коэффициенты и выделяю те процессы, которые значительно отклоняются от общесистемных тенденций. Если остаются сомнения, я повторяю измерение не менее трёх раз. Только стабильные отклонения я считаю достоверными. Для постоянного мониторинга я сопоставляю счетчики с временными рядами и связываю их с метаданными релизов — таким образом я выявляю Точки регрессии немедленно.

Контрольный список для систематической настройки NUMA

  • Определение цели: латентность против пропускной способности, фиксированная нагрузка против переменной
  • Отображение топологии: узлы, задержки, свободные резервы ОЗУ на каждый узел
  • Измерение базовых показателей: общий показатель numastat и показатель по каждому процессу, расчет коэффициентов
  • Корректировка размещения: аффинность процессора, привязка к памяти, политики
  • Настройка контейнеров/виртуальных машин: cpuset.cpus = узел, cpuset.mems — соответствующие значения; правильное отображение vNUMA
  • Осознанный выбор THP/Hugepages, контроль фрагментации
  • Снижение нагрузки на память: проверьте запас памяти для каждого узла и стратегию использования файла подкачки
  • Повторные измерения: сравнение дельт, обеспечение стабильности во времени
  • Документирование: привязки в виде кода, примечания к выпуску с учетом контекста NUMA

Краткое резюме

Я анализирую данные NUMA следующим образом: Сигналы В этом контексте см.: пары счетчиков, временные графики и представление процессов. Ключевые значения numa_hit, numa_miss, numa_foreign, local_node, other_node и interleave_hit показывают мне локальность, переключения и стратегии распределения. Я принимаю решения на основе топологии и рабочей нагрузки, а не исходя из жестких пороговых значений. Настройка начинается с размещения, аффинности, подходящей политики и четкой процедуры измерения. Так я обеспечиваю стабильную Производительность, поскольку процессор и объем оперативной памяти соответствуют требованиям приложения, а передача данных на большие расстояния происходит редко.

Текущие статьи

Техническая серверная инфраструктура с акцентом на анализ NUMA в Linux
Серверы и виртуальные машины

Правильный анализ статистики NUMA в Linux

Как правильно анализировать статистику NUMA в Linux: понимание статистики NUMA, проверка локальности памяти и целенаправленное повышение производительности сервера.

Абстрактное фотореалистичное изображение системы контроля доступа Redis в серверной среде
Безопасность

Безопасное использование списков контроля доступа Redis в многопользовательских средах

Списки контроля доступа (ACL) Redis для многопользовательских сред обеспечивают повышенную безопасность Redis за счет четкого распределения прав пользователей, правил доступа к ключам и контролируемого доступа.

Серверная стойка с работающим сервером базы данных MariaDB в современном центре обработки данных
Базы данных

Как избежать снижения производительности MariaDB после обновлений

Узнайте, как избежать снижения производительности MariaDB после обновления mariadb и обеспечить стабильную и быструю работу баз данных с помощью целенаправленной настройки.