MAATRIX / Блог / После переезда всё стало вдвое медленнее: у нового CPU отключили турбо

После переезда всё стало вдвое медленнее: у нового CPU отключили турбо

MAATRIX

Переезд планировали как повышение — новый сервер брали с запасом по ядрам, памяти и более свежим поколением процессора, старый уже не тянул растущую нагрузку. А после переключения продакшена всё стало заметно тормозить: API отвечал медленнее, фоновые джобы растягивались, отчёты, которые раньше укладывались в обеденный перерыв, к вечеру ещё не заканчивались. И самое неприятное — ни один из привычных подозреваемых не подтверждался: диск быстрый, сеть чистая, код тот же самый. Разгадка нашлась там, где её меньше всего ждали — в настройках BIOS, которые на новом железе выставили не так, как на старом.

Что заметили в первые часы после переезда

Миграцию делали ночью, по плану: снять снапшот, поднять сервисы на новом сервере, переключить DNS и балансировщик, старый оставить в резерве на неделю. Технически всё прошло гладко — приложение стартовало, health-check зелёные, ошибок в логах нет. Проблему увидели не сразу, а когда начал приходить дневной трафик.

Первый сигнал — дашборд с задержками API. p95 по ключевым эндпоинтам вырос примерно вдвое относительно того, что было на старом сервере накануне. Не всплеск на пару минут, а ровное, устойчивое ухудшение по всем маршрутам сразу — и по тем, что бьют в базу, и по тем, что просто отдают статику из кеша. Второй сигнал — время выполнения ночных batch-джобов и ETL: то, что раньше укладывалось в фиксированное окно, начало вылезать за его границы.

Загрузка CPU при этом выглядела спокойно: top и htop показывали умеренный %us, свободные ядра были, load average не зашкаливал. Именно это сбивало с толку сильнее всего — по всем классическим признакам сервер не был перегружен, но работал заметно медленнее старого при той же нагрузке.

Первый круг подозреваемых: сеть, диск, конфигурация ОС

Первым делом проверили самое очевидное и самое частое при переездах:

  • Сеть. Прогнали iperf3 между новым сервером и остальной инфраструктурой, посмотрели ping/mtr до базы и до внешних API. Полоса и задержки были в пределах ожидаемого для этого дата-центра, аномалий не нашли.
  • Диск. Проверили fio на случайное чтение/запись, сравнили с показателями старого сервера (они были зафиксированы в внутренней вики после прошлой миграции). NVMe на новом сервере был не хуже, местами быстрее.
  • Конфигурация ОС. Сверили sysctl -a на старом и новом сервере построчно через diff, проверили лимиты в /etc/security/limits.conf, параметры файловой системы (noatime, планировщик ввода-вывода). Расхождения были, но некритичные — типичный шум между двумя разными установками ОС.
  • Docker и cgroup-лимиты. Приложение крутилось в контейнерах, поэтому проверили docker stats, лимиты --cpus и --memory в compose-файлах. Лимиты скопировали с прошлой конфигурации один в один, ничего не резалось искусственно.

Ни один пункт не объяснял устойчивое замедление вдвое по всем видам нагрузки одновременно. Стало ясно, что дело не в сети и не в диске — узкое место было либо в самом CPU, либо в том, как гипервизор или прошивка его отдавали.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Второй круг: база данных и рантайм приложения

Следующим шагом полезли внутрь приложения, предположив, что дело в конфигурации сервисов, а не в железе:

  • Сравнили версии рантайма и зависимостей на старом и новом сервере — версии совпадали, разница в патч-релизах была, но не в тех компонентах, что грузят CPU.
  • Проверили план выполнения тяжёлых SQL-запросов через EXPLAIN ANALYZE — планы были идентичны на старом и новом сервере, использовались те же индексы, число строк на входе и выходе совпадало.
  • Посмотрели на GC-паузы у сервисов на JVM — паузы были чуть длиннее, но пропорционально, не вдвое, и не объясняли масштаб проблемы для сервисов на других языках, которые тормозили так же.
  • Проверили, не переехала ли часть трафика на менее мощный узел кластера по ошибке балансировки — нет, весь трафик шёл на новый сервер, как и планировалось.

На этом этапе стало понятно: искать баг в приложении бессмысленно, потому что тормозило абсолютно всё — от простых статических ответов до сложных агрегаций в базе. Единственное, что объединяет все виды нагрузки, — это то, как ЦПУ исполняет инструкции. Значит, смотреть нужно было не на загрузку, а на частоту.

Поворотный момент: частота вместо загрузки

Стандартные метрики мониторинга показывали проценты использования ядер, но не показывали, на какой реальной частоте эти ядра работают. Это ключевая слепая зона многих дашбордов: %CPU в top считается относительно текущей тактовой частоты, а не относительно паспортного максимума. Если ядро работает на пониженной частоте, но занято на 80% своего времени, вы увидите те же 80%, что и на полной частоте — просто полезной работы будет сделано меньше.

Проверили частоту напрямую:

watch -n 1 "cat /proc/cpuinfo | grep MHz"

и через turbostat (пакет linux-tools-common):

turbostat --interval 2

Результат объяснил всё. На старом сервере ядра при нагрузке разгонялись заметно выше базовой частоты — так и должен работать Turbo Boost (у Intel) или Precision Boost / Core Performance Boost (у AMD): под нагрузкой процессор поднимает частоту одного или нескольких ядер выше номинала, пока позволяет теплопакет. На новом сервере частота под той же нагрузкой упорно держалась ровно на базовом значении, ни разу не поднимаясь выше — как будто турбо-режим физически отсутствовал.

Для приложений с большой долей однопоточной или слабо распараллеленной работы (а именно так устроена типичная обработка HTTP-запроса или один SQL-запрос) разница между базовой и турбо-частотой напрямую превращается в разницу в задержке. Более новое поколение CPU с бОльшим числом ядер по паспорту совершенно не гарантирует более высокую частоту на ядро — если буст выключен, младшая по паспорту, но с активным турбо машина обгонит её на латентных задачах.

Где нашлось отключённое турбо

Дальше пошли по цепочке настроек, которые могут гасить буст, от программных к аппаратным:

  1. Governor в Linux. Проверили cpupower frequency-info. Governor стоял в performance, не в powersave — с этой стороны всё было настроено правильно, программной блокировки буста через governor не было.
  2. Ограничения в гипервизоре. Сервер был выделенным (bare metal), без слоя виртуализации между ОС и железом, так что лимиты гипервизора на частоту исключили сразу — их просто не существовало в этой конфигурации.
  3. BIOS/UEFI. Зашли через IPMI/iDRAC-подобную консоль провайдера в настройки прошивки. И вот здесь нашлась причина: в профиле питания стоял режим энергоэффективности («Performance Per Watt» / аналогичный пункт в зависимости от производителя платы) вместо режима максимальной производительности, а сам пункт Turbo Boost/Core Performance Boost был выставлен в Disabled.

Это стандартная заводская настройка для части серверных платформ, ориентированных на плотность и экономию электричества в дата-центре, а не на пиковую производительность одного узла — провайдер разворачивает новые серверы из шаблона, и если в шаблоне энергоэффективный профиль, буст будет выключен у всех, кто получит сервер из этого пула, пока не поменяет вручную. На старом сервере в своё время профиль питания перенастраивали руками ещё при первом вводе в эксплуатацию — и это просто забыли задокументировать и повторить при заказе нового железа.

Что изменили и как проверили, что это оно

План действий был короткий, но каждый шаг проверяли отдельно, чтобы не свалить в одну кучу несколько изменений и не потерять причинно-следственную связь:

  1. В BIOS сменили профиль питания на «Maximum Performance» (или её аналог у конкретного производителя платы) и явно включили Turbo Boost / Core Performance Boost.
  2. После перезагрузки повторно сняли частоту через turbostat под той же синтетической нагрузкой (несколько параллельных запросов через wrk на тестовый эндпоинт) — ядра начали подниматься выше базовой частоты под нагрузкой, как и ожидалось.
  3. Прогнали тот же набор запросов, что использовали для диагностики (тяжёлые SQL-запросы, тестовый прогон batch-джобы на урезанном наборе данных) — время выполнения вернулось к уровню, сопоставимому со старым сервером.
  4. Постепенно перевели часть боевого трафика обратно на новый сервер, продолжая сравнивать p95 по дашборду в реальном времени, прежде чем переключать всё целиком.

Отдельно завели чек-лист приёмки нового сервера, куда добавили явный пункт: снять частоту CPU под нагрузкой через turbostat и сверить с ожидаемой турбо-частотой из спецификации производителя, до того как сервер уедет в продакшен. Раньше приёмка ограничивалась проверкой места на диске, версии ядра и доступности портов — частота CPU туда просто не входила, потому что для облачных инстансов, где буст обычно не в руках заказчика, этот вопрос никогда не поднимался. При переходе на выделенное железо появился новый параметр, который раньше был не нужен, и его забыли добавить в процесс.

Как не наступить на те же грабли при переезде на новый сервер

Несколько практических выводов, которые стоит забрать себе на будущее, если планируете переезд с облака на выделенный сервер или просто смену железа внутри одного провайдера:

  • Проверяйте частоту CPU под нагрузкой сразу после ввода сервера в эксплуатацию, а не только доступность сервисов. turbostat или простое чтение /proc/cpuinfo в цикле занимает пару минут, а экономит дни разбора инцидента.
  • Не полагайтесь только на %CPU в мониторинге — добавьте на дашборд текущую частоту ядер, это дешёвая метрика, которая сразу подсвечивает подобные ситуации. Заодно она помогает отличить троттлинг от чужой активности на соседе по гипервизору, если сервер не выделенный, а виртуальный, — там похожая просадка производительности выглядит иначе в метриках, но тоже не видна в голом проценте загрузки.
  • Заведите чек-лист приёмки железа с явными пунктами: профиль питания в BIOS, статус Turbo Boost / Core Performance Boost, governor в ОС, актуальная версия микрокода. Один документ, который проходит каждый новый сервер, дешевле, чем повторное расследование одного и того же инцидента через год.
  • Сравнивайте не только паспортные характеристики (число ядер, объём памяти), но и реальные результаты небольшого нагрузочного теста на новом сервере до переключения продакшена — синтетика не заменит боевой трафик, но грубую деградацию покажет заранее.
  • Если выбираете между разными линейками процессоров для нового сервера, учитывайте не только частоту и число ядер по спецификации, но и то, насколько предсказуемо провайдер настраивает буст из коробки — это отдельный практический критерий, который редко попадает в сравнительные таблицы, хотя влияет на латентность не меньше, чем архитектура самого чипа.
  • Документируйте нестандартные настройки BIOS, которые меняли вручную на предыдущем сервере — иначе при следующей замене железа они просто потеряются вместе с той машиной, а разбираться придётся заново с нуля, как в этом случае.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Как быстро проверить, включён ли Turbo Boost, без захода в BIOS?

Дайте серверу однопоточную нагрузку (например, stress-ng --cpu 1) и одновременно смотрите частоту через turbostat --interval 1 или watch -n1 "cat /proc/cpuinfo | grep MHz". Если частота под нагрузкой не поднимается выше базовой, скорее всего буст выключен в прошивке или заблокирован governor'ом.

Может ли governor в Linux сам ограничивать буст, даже если он включён в BIOS?

Да. Governor powersave держит ядра ближе к минимальной частоте и не даёт им активно подниматься даже при включённом в BIOS Turbo Boost. Для нагруженных серверов обычно ставят performance через cpupower frequency-set -g performance, но это не отменяет проверку самого BIOS — оба уровня настроек должны быть согласованы.

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

Потому что %CPU показывает долю времени, в течение которого ядро было занято, а не то, сколько реальной работы оно успело сделать за это время. Ядро на пониженной частоте может быть занято те же 80% времени, что и на полной, просто выполнит меньше инструкций — отсюда рост задержек без видимого роста загрузки.

Стоит ли просить провайдера сразу настраивать профиль питания при заказе выделенного сервера?

Да, это разумный практический шаг: попросите явно зафиксировать профиль питания «Maximum Performance» и включённый Turbo Boost/Core Performance Boost в заявке или сразу после получения доступа, не полагаясь на заводской шаблон — это экономит один полный цикл диагностики, аналогичный описанному выше.

Влияет ли этот же эффект на виртуальные серверы (VPS), или это проблема только выделенных машин?

На VPS буст зависит от настроек хост-узла и от того, сколько CPU-ресурсов вам реально выделено помимо заявленных vCPU — управлять BIOS напрямую вы там не можете, и картина обычно ближе к steal time и конкуренции с соседями по гипервизору, а не к отключённому бусту. На bare metal вы отвечаете за настройку прошивки сами, поэтому и разбираться приходится на этом уровне.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →