Просадки производительности на VDS часто выглядят одинаково: нагрузка есть, load average растёт, а запросы внезапно выполняются в 2–5 раз дольше. При этом на графиках CPU может не быть 100% — либо ядра «залипают» на пониженной частоте. Это типичный сценарий throttling: процессор ограничивает частоту или планировщик ограничивает время исполнения из-за лимитов мощности (TDP/PL), температуры, энергополитик или квот CPU в cgroups.
Ниже — практический разбор, как отличать причины, какие подсистемы Linux участвуют (intel_pstate, cpufreq, turbo), где смотреть лимиты мощности (powercap/RAPL), как быстро измерять (turbostat, perf), и как контролировать квоты в cgroups v2 через cpu.max и systemd slices.
Что именно называется throttling: три разных механизма
Важно разделить «тормоза CPU» на классы. Симптомы похожи, но действия по исправлению — разные.
1) Thermal throttling (температурный)
CPU снижает частоту/напряжение, когда упирается в температурный лимит. На физическом сервере это часто связано с охлаждением и обдувом. На VDS вентиляторами вы не управляете, но последствия видите в гостевой ОС: частота падает, задержки растут.
2) TDP-limit / power limit (ограничение по мощности)
Современные Intel/AMD ограничивают потребление через power limits (у Intel обычно PL1/PL2). Даже при нормальной температуре процессор может резать частоту, чтобы уложиться в заданный лимит мощности. В реальности это один из самых частых «неожиданных» сценариев: под длительной нагрузкой частота стабилизируется ниже ожидаемой.
3) Квоты/шаринг на уровне виртуализации и cgroups
- CPU steal time: гипервизор отнимает время у вашей VM, потому что физические ядра заняты другими гостями. Внутри Linux это видно как
stealвtop/vmstat. - Лимиты cgroups: вы сами (или панель/оркестратор) ограничили сервисам CPU через cgroups v2. Тогда процессы «душатся» по расписанию: им не дадут больше N микросекунд CPU на период (см.
cpu.max).
Быстрый чек‑лист: чем вызваны просадки на VDS
Когда есть инцидент и нужно понять «кто виноват» за 5–10 минут, начните с минимального набора проверок.
Шаг 1. Проверить steal time
top -b -n 1 | head -n 15
В строке CPU в top смотрите st. Если st заметно ненулевой (условно 5–20% и выше на длительном интервале), это сильный кандидат на проблемы уровня гипервизора/переподписки CPU: вы просто ждёте, пока VM дадут исполняться.
vmstat 1 10
В колонке st будет steal.
Шаг 2. Проверить текущие частоты и драйвер (intel_pstate / cpufreq)
uname -r
lscpu | egrep -i 'model name|mhz|cpu\(s\)|thread|core|socket'
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver 2>/dev/null || echo no-cpufreq
Если видите intel_pstate — это обычный современный вариант для Intel. Если acpi-cpufreq — управление частотой идёт через классический cpufreq-драйвер. Если файла нет, возможно, в VM частоты «спрятаны» гипервизором, и детальную телеметрию вы не увидите.
Шаг 3. Посмотреть governor и ограничения
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 2>/dev/null
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 2>/dev/null
Если scaling_max_freq неожиданно низкий — возможно, выставлен лимит частоты политикой ядра или окружением (включая настройки хоста).

Шаг 4. Снять turbostat: есть ли признаки ограничений
turbostat — один из лучших инструментов для диагностики turbo, idle‑состояний и ограничений. На Debian/Ubuntu обычно ставится из пакета linux-tools (название пакета зависит от ядра).
turbostat --Summary --interval 1 --num_iterations 10
Что смотреть в выводе:
- падает ли
Bzy_MHzпод нагрузкой и «не поднимается»; - есть ли признаки ограничений по мощности/температуре (зависит от модели CPU и доступности MSR);
- не слишком ли много времени CPU проводит в idle при «вроде бы» высокой нагрузке (тогда проблема может быть не в CPU, а в I/O/локах).
Если turbostat в VM ничего полезного не показывает или ругается на недоступные MSR/PMU — это ограничение виртуализации. Тогда опирайтесь на косвенные признаки: стабильная низкая частота, отсутствие роста при нагрузке и рост времени выполнения задач при неизменном коде.
Как работает intel_pstate, cpufreq и turbo (и где легко ошибиться)
Частая ошибка: думать, что governor performance автоматически держит максимум частоты всегда. На современных Intel с intel_pstate реальная частота — это компромисс между запросом нагрузки, лимитами мощности/температуры и энергополитикой.
intel_pstate: active/passive и EPP
У intel_pstate есть два основных режима:
- active: драйвер сам управляет P‑states, а классические governors ведут себя не так, как вы ожидаете по старым гайдам;
- passive: управление через стандартный cpufreq-интерфейс и governors.
На некоторых системах доступна настройка EPP (Energy Performance Preference) — она может «держать» частоты ниже, чем ожидается, даже если в целом выбран производительный профиль. Проверка (если интерфейс доступен):
cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference 2>/dev/null
Почему «не бустится» turbo
Turbo почти всегда упирается в один из лимитов:
- температура (thermal throttling);
- лимиты мощности PL1/PL2 (TDP/power limit);
- ограничение максимальной частоты политикой;
- в виртуализации — ограничения хоста или политика провайдера.
Для Intel состояние turbo нередко видно так:
cat /sys/devices/system/cpu/intel_pstate/no_turbo 2>/dev/null
Значение 1 обычно означает «turbo выключен». Но даже при 0 turbo может не проявляться, если срабатывает power limit.
Powercap и TDP-limit: где в Linux живут лимиты мощности
Подсистема powercap в Linux даёт интерфейс к RAPL (Running Average Power Limit) на Intel. На «железе» это позволяет увидеть (а иногда и настроить) лимиты мощности. На VDS доступность зависит от гипервизора: часто RAPL скрывают.
Проверка наличия powercap:
ls -1 /sys/class/powercap 2>/dev/null || echo no-powercap
Если каталог есть, можно исследовать содержимое (названия доменов отличаются):
find /sys/class/powercap -maxdepth 3 -type f -name 'name' -o -name 'enabled' -o -name 'constraint_*_power_limit_uw' 2>/dev/null
Практический смысл:
- если долгий лимит (аналог PL1) слишком низкий, CPU будет стабильно работать на «неожиданно» низких частотах под длительной нагрузкой;
- если лимит короткого буста (аналог PL2) низкий, не будет коротких «взлётов» частоты на пиках.
На большинстве VDS вы не сможете менять RAPL/PL1/PL2 из гостя, даже если что-то видно. Но диагностика полезна: вы хотя бы докажете, что упёрлись именно в power limit, а не в «плохой код».
cgroups v2: cpu.max, cpu.weight и почему сервис «душится» при свободном CPU
Если система на unified hierarchy (cgroups v2), ограничения CPU задаются иначе, чем в v1. Главный файл — cpu.max. Он задаёт квоту и период: сколько времени CPU можно потреблять за период. Это «throttling» планировщика, а не железа.
Как проверить, что система на cgroups v2
stat -fc %T /sys/fs/cgroup
Если увидите cgroup2fs — это v2.
Посмотреть лимиты для текущего процесса
Для быстрой диагностики удобно начать с PID проблемного процесса:
PID=1234
cat /proc/$PID/cgroup
Дальше найдите соответствующий каталог в /sys/fs/cgroup и проверьте:
CG=/sys/fs/cgroup/your.slice/your.service
cat $CG/cpu.max
cat $CG/cpu.stat
cat $CG/cpu.weight 2>/dev/null
Как интерпретировать:
cpu.maxвидаmax 100000— квоты нет (безлимит), период 100 ms.cpu.maxвида20000 100000— квота 20 ms на 100 ms, то есть 20% одного CPU.cpu.statсодержит счётчики throttling (часто поляnr_throttled,throttled_usec). Их рост под нагрузкой — прямое подтверждение cgroup‑throttling.
systemd slices: где чаще всего «прячут» лимиты
На системах с systemd ограничения часто задаются декларативно через unit‑файлы и slices. Типовые сценарии:
- панель/оркестратор ограничил группу сервисов в отдельном slice;
- вы ограничили фоновые задачи через
CPUQuota=и забыли, а в пике получили задержки; - в контейнерной среде лимит выставлен контейнеру, а приложение думает, что у него все ядра.
Проверить ограничения systemd для конкретного сервиса:
systemctl show your.service -p CPUQuota -p CPUQuotaPeriodSec -p Slice -p AllowedCPUs
А для slice целиком:
systemctl show your.slice -p CPUQuota -p CPUQuotaPeriodSec -p AllowedCPUs
Если хотите глубже разобраться в лимитах systemd (CPU/Memory/Tasks), полезно держать под рукой материал: лимиты systemd для CPU и памяти.
perf: как отличить «CPU медленнее» от «CPU не дают»
perf полезен в двух ситуациях: (1) вы подозреваете, что частоты упали (TDP/thermal), (2) вы подозреваете cgroup/steal и хотите увидеть, что процесс больше ждёт, чем считает.
Быстрый профиль без flamegraph
perf stat -p 1234 -- sleep 10
Смотрите на:
task-clockи долю времени в CPU;context-switchesиcpu-migrations(могут резко расти при перегрузе/квотах/лишних воркерах);- инструкции/циклы (если доступны): на VDS PMU может быть недоступен, это нормально.
Системный взгляд на нагрузку
perf top
Если в топе в основном планировщик/синхронизация, а не «полезная работа» приложения, то проблема часто не в «медленном CPU», а в contention, ожиданиях, блокировках или ограничении по квоте.
Типовые причины просадок на VDS и что с ними делать
Сценарий A: частота не растёт, ограничения по мощности/температуре
- Признаки: steal низкий; задержки растут; частота по наблюдениям низкая и почти не меняется под нагрузкой; на железе turbostat/датчики показывают ограничения.
- Действия: на своём железе проверьте охлаждение и powercap; на VDS фиксируйте факт (время, нагрузка, вывод turbostat при возможности) и эскалируйте провайдеру; со стороны приложения снижайте пики (ограничение параллелизма, очереди, backpressure), чтобы не загонять CPU в длительный power‑limit режим.
Сценарий B: высокий steal time
- Признаки: заметный
stвtop/vmstat; при том же QPS задержки «плавают»; частота может быть нормальной. - Действия: соберите историю
stво время инцидента и сопоставьте с latency; изнутри VM это не лечится; часто помогает переход на более предсказуемый класс виртуализации или увеличение vCPU.
Сценарий C: cgroups v2 cpu.max ограничивает сервис
- Признаки: steal низкий; в
cpu.statрастёт throttling; общесистемно CPU «свободен», но сервис не выходит за определённый процент. - Действия: найдите место, где задан лимит (unit systemd, slice, контейнерный runtime); разделите сервисы по slices (интерактивный веб без жёсткой квоты, фон с квотой и меньшим весом через
cpu.weight); проверьте соответствие квоты модели параллелизма (например, 20% одного CPU при 8 воркерах даст лишние переключения контекста).

Практика: аккуратное управление CPU лимитами через systemd (cgroups v2)
Подход для типичного VDS с вебом и фоновой обработкой: вебу — низкая задержка, фону — предсказуемое потребление, чтобы не устраивать конкуренцию в пике.
Создаём отдельный slice для фоновых задач
Сделайте drop‑in для slice:
mkdir -p /etc/systemd/system/background.slice.d
cat > /etc/systemd/system/background.slice.d/10-cpu.conf << 'EOF'
[Slice]
CPUQuota=50%
CPUWeight=100
EOF
systemctl daemon-reload
Применение настроек для slice обычно достаточно сделать через перезапуск сервисов, которые в него входят. Если slice уже используется, можно перезапустить связанные сервисы; сам slice как «юнит» перезапускают не всегда, поэтому ориентируйтесь на факт изменения параметров в cgroup‑файлах.
Назначаем сервису slice
systemctl edit workers.service
[Service]
Slice=background.slice
systemctl daemon-reload
systemctl restart workers.service
Проверка результата:
systemctl show workers.service -p Slice -p CPUQuota
cat /sys/fs/cgroup/background.slice/cpu.max
cat /sys/fs/cgroup/background.slice/cpu.stat
Нюансы в контейнерах: когда cpufreq «ни при чём»
В контейнерах частая ловушка — искать проблему в intel_pstate/cpufreq, когда на самом деле контейнеру выставили квоту CPU. Для cgroups v2 это тот же cpu.max, но в дереве cgroup контейнера. Признак прежний: растёт throttling в cpu.stat, а приложение не масштабируется по воркерам.
Практический совет: заставьте приложение подстраивать число воркеров под фактическую квоту, а не под число «видимых» CPU. Иначе получите лишние переключения контекста и рост latency даже при «свободном» хосте.
Резюме: как не гадать, а доказывать причину throttling
Чтобы уверенно объяснить «почему стало медленно», собирайте доказательства по слоям:
- Гипервизор/шаринг:
stealвtop/vmstat. - cgroups v2:
cpu.maxи рост throttling вcpu.stat. - Частота/boost: данные
turbostat(если доступны) и cpufreq‑интерфейсы (scaling_driver,scaling_max_freq,no_turbo). - Профиль нагрузки:
perf stat/perf topчтобы отделить «CPU медленнее» от «CPU не дают» и от проблем синхронизации.
Если по итогам видно, что вы упёрлись в хост‑уровень (power/thermal/steal) и нужна предсказуемая производительность, имеет смысл выбирать тарифы и ресурсы под пиковую нагрузку: например, перейти на VDS с подходящим числом vCPU и стабильными лимитами.
А если «тормоза» оказались на уровне диска, а не CPU, полезно свериться с практикой измерений и тюнинга I/O: диагностика дисковой подсистемы (iostat/iotop/fio).


