Системный администратор видит в задаче настройки CPU governor простой выбор из двух строк. Запустить одну команду - и готово, сервер переключается в другой режим. Но за этой простотой скрывается многоуровневая архитектура, которая работает принципиально по-разному в зависимости от поколения процессора, драйвера ядра и конкретной рабочей нагрузки. Два сервера с одинаковым CPU и одинаковым governor могут демонстрировать разные результаты просто потому, что на одном установлен Linux 6.10, а на другом - 6.6.

Понять, почему так происходит, значит перестать угадывать и начать осознанно управлять производительностью.

Governors - это не то, что кажется на первый взгляд

Традиционное объяснение звучит просто: performance держит частоту на максимуме, powersave - на минимуме. Это правда, но только для старого драйвера acpi-cpufreq, который сегодня встречается разве что на процессорах до Skylake (6-е поколение Intel) или на очень старых AMD. На любом современном чипе с intel_pstate или amd_pstate картина куда интереснее.

На Intel начиная со Skylake работает аппаратный механизм HWP - Hardware P-States, или Intel Speed Shift. При активном режиме intel_pstate governors performance и powersave превращаются в подсказки для внутреннего контроллера чипа через параметр EPP - Energy Performance Preference. Оба режима по-прежнему обеспечивают динамическое масштабирование частоты - разница лишь в том, насколько агрессивно процессор стремится к высоким частотам при кратковременных нагрузках. Governor performance с EPP 0 говорит чипу "стремись к максимуму", powersave с EPP 128 - "работай эффективнее". Процессор при этом в обоих случаях снижает частоту в простое.

Проверить, какой драйвер и governor сейчас активны:

cpupower frequency-info
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver
cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference

Если в выводе первой команды видно driver: intel_pstate и режим active, переключение governor напрямую меняет EPP. Если же драйвер - intel_cpufreq (пассивный режим), то governor работает по старой схеме и performance действительно фиксирует частоту у верхней границы.

Почему Intel 11-го поколения вёл себя аномально

Тест на i9-11900K стал показательным кейсом в истории CPU governors. Переключение с powersave на performance дало не обычные 2-4% прироста, которые наблюдались на предыдущих поколениях Intel, а около 9% в среднем по 156 бенчмаркам - с пиками до 20-30% в браузерных тестах и Python-нагрузках. Одновременно среднее энергопотребление выросло примерно на 37%.

Причина - специфика Cypress Cove: ядра Rocket Lake оказались крайне чувствительными к тому, насколько быстро HWP реагирует на всплески нагрузки. При powersave EPP держал контроллер в режиме осторожной реакции, и ядра не успевали разгоняться до буст-частот в пределах коротких вычислительных окон. Более поздние поколения - Alder Lake, Raptor Lake, Meteor Lake - показывают куда меньшую разницу (2-5%), потому что алгоритм HWP был доработан, а latency перехода между P-state снизилась.

На практике это означает: перед тем как менять governor в продакшене, стоит промерить разницу именно на своём поколении CPU:

# Установить performance и измерить время компиляции или другого реального теста
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
time make -j$(nproc)

# Переключить на powersave и повторить
echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
time make -j$(nproc)

AMD и три уровня контроля над частотой

AMD шла к своему решению другим путём. До появления amd_pstate все процессоры Ryzen и EPYC работали через acpi-cpufreq - тот самый старый драйвер, где performance и powersave действительно означали "максимум" и "минимум". Результат был предсказуем: в серверных нагрузках оставались либо потери производительности, либо высокое энергопотребление без возможности тонкой настройки.

Начиная с ядра 5.17 для Zen 2 и 6.1 для Zen 3 появился amd_pstate, а в 6.3 - amd_pstate_epp, который включается параметром amd_pstate=active в cmdline. Архитектура напоминает intel_pstate, но с важным отличием: механизм CPPC (Collaborative Processor Performance Control) позволяет операционной системе общаться с прошивкой через стандартизированный интерфейс ACPI, задавая не конкретные частоты, а целевые уровни производительности. Прошивка сама учитывает температуру, напряжение, состояние питания и уже на основе всего этого выбирает реальную частоту.

Для EPYC 9005 (Turin, Zen 5) в ядре 6.13 amd_pstate стал дефолтным драйвером, и тестирование показало, что конфигурация powersave governor + EPP performance обеспечивает на некоторых нагрузках лучшую производительность на ватт, чем прямолинейный performance governor + EPP performance. Это кажется парадоксальным, пока не понимаешь: powersave в этом контексте не ограничивает максимальную частоту - он лишь говорит прошивке "не гонись за буст-частотой в простое, экономь". А EPP performance уже инструктирует: "когда нагрузка есть - работай агрессивно".

Включить amd_pstate active mode и выставить EPP:

# В GRUB добавить в GRUB_CMDLINE_LINUX:
# amd_pstate=active

# После перезагрузки установить EPP для всех ядер
echo performance | sudo tee \
  /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference

# Проверить текущие EPP-значения
grep . /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference | head -4

Latency перехода и почему это важно для серверных задач

Одна метрика, которую часто игнорируют при разговоре о governors, - это время перехода между P-state. Когда рабочая нагрузка внезапно требует полной производительности, сколько микросекунд проходит до того, как ядро выходит на нужную частоту?

У старого acpi-cpufreq с governor ondemand интервал опроса нагрузки составлял 10-50 миллисекунд. За это время короткий всплеск вычислений мог завершиться раньше, чем частота успевала вырасти. Intel Speed Shift снизил latency перехода до примерно 1 миллисекунды. AMD CPPC на Zen 4 и Zen 5 работает с comparable latency благодаря прямому взаимодействию с контроллером частоты без обращения к ACPI.

Именно поэтому на современных CPU разница между governors в однопоточных нагрузках с редкими всплесками активности куда заметнее, чем при постоянной нагрузке близкой к 100%. При непрерывной нагрузке оба governor выходят на одинаковую частоту - разница лишь в том, насколько быстро они это делают в начале задачи.

Измерить реальную latency перехода для конкретного CPU:

# Утилита из пакета linux-tools или kernel-tools
turbostat --interval 0.1 --show CPU,Busy%,Bzy_MHz,PkgWatt \
  -- taskset -c 0 stress-ng --cpu 1 --timeout 10s

Разница между пиковой и минимальной частотой в колонке Bzy_MHz в первые секунды нагрузки покажет, насколько быстро CPU реагирует на переход от простоя к полной нагрузке.

C-state и их взаимодействие с governor

Отдельная тема, без которой картина остаётся неполной, - C-states, состояния глубокого простоя ядер. Governor управляет P-state (частотой в активном состоянии), но C-state управляет тем, насколько глубоко ядро "засыпает" в простое.

При governor performance на Intel CPU ядра также по умолчанию могут входить в C6/C7, полностью отключая питание на домен ядра. Когда нагрузка возвращается, выход из C6 занимает от 100 до 300 микросекунд - куда больше, чем переход между P-state. Для сервисов с жёсткими требованиями к latency (высокочастотная торговля, realtime-обработка данных, игровые серверы) это становится заметной проблемой независимо от выбранного governor.

Контролировать C-state можно независимо от governor:

# Запретить глубокие C-state через параметр ядра (постоянно)
# В GRUB_CMDLINE_LINUX добавить: intel_idle.max_cstate=1

# Временно для конкретного ядра через cpupower
sudo cpupower idle-set -D 2     # Запретить состояния глубже C2

# Или через прямую запись в sysfs
for cpu in /sys/devices/system/cpu/cpu*/cpuidle/state*/disable; do
  echo 1 | sudo tee "$cpu" > /dev/null
done

Комбинация performance governor с ограничением C-state - стандартная практика для latency-sensitive нагрузок в production. На AMD Zen 4 и Zen 5 аналогичный эффект достигается через параметр processor.max_cstate=1 в cmdline.

Постоянная настройка через systemd и cpupower

Ручное переключение через sysfs не переживает перезагрузку. Для production-серверов governor фиксируется через systemd-сервис или конфигурацию cpupower.

Создать systemd-unit для автоматического применения настроек при загрузке:

# /etc/systemd/system/cpu-governor.service
[Unit]
Description=Set CPU governor and EPP
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor'
ExecStart=/bin/bash -c 'echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Или через стандартный конфигурационный файл cpupower:

# /etc/default/cpupower
CPUPOWER_START_OPTS="frequency-set -g performance"
sudo systemctl enable cpupower

Для AMD с amd_pstate_epp рекомендованная конфигурация AMD-инженеров для максимальной эффективности на Zen 5 - powersave governor плюс EPP performance через energy_performance_preference. Для максимальной производительности без компромиссов - performance governor плюс EPP performance, с пониманием того, что энергопотребление в простое вырастет.

Правильный ответ на вопрос "какой governor использовать" начинается не с выбора между двумя словами, а с понимания того, какой именно драйвер работает под ними. Один и тот же governor performance на i5 из 2014 года и на Ryzen 9 из 2024 - это технически разные механизмы с разными алгоритмами, разной реакцией на нагрузку и разными рычагами тонкой настройки. Инструменты для этого понимания - cpupower, turbostat, и несколько строк в sysfs - всегда под рукой.