The Problem Most People Ignore
Your Linux server is crawling through batch jobs. Your laptop fan won’t stop spinning during light use. You’ve tuned the application, checked memory, and audited disk I/O — still slow. The CPU governor has been sitting on powersave the whole time, quietly capping clock speed to whatever minimum the kernel can justify.
That’s CPU frequency scaling doing exactly what it was designed to do. Just not what you intended. The kernel dynamically adjusts CPU clock speed based on load, using a policy called a governor. The default on many distros favors power saving over performance — fine for idle machines, terrible when you need consistent throughput.
Here’s how to inspect, change, and permanently control CPU frequency governors using cpupower and cpufreq-utils — the two main toolsets for this job on modern Linux systems.
Quick Start — Get Running in 5 Minutes
Install the Tools
On Ubuntu/Debian:
sudo apt update
sudo apt install linux-tools-common linux-tools-$(uname -r) cpufrequtils
On Fedora/RHEL/AlmaLinux:
sudo dnf install kernel-tools
On Arch Linux:
sudo pacman -S cpupower
Check Your Current Governor
cpupower frequency-info
You’ll see output like:
analyzing CPU 0:
driver: intel_pstate
CPUs which run at the same hardware frequency: 0
available cpufreq governors: performance powersave
current policy: frequency should be within 400 MHz and 3.60 GHz
current CPU frequency: 800 MHz (asserted by call to hardware)
boost state support: supported - enabled
See that current CPU frequency: 800 MHz? Your CPU is running at its floor. If you’re doing anything CPU-intensive, that’s your bottleneck right there.
Switch to Performance Mode
sudo cpupower frequency-set -g performance
Verify it took effect:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Should print: performance
Deep Dive — How CPU Frequency Scaling Works
The Governor Lineup
Linux ships with several governors. Which ones are available depends on your CPU driver (intel_pstate, amd-pstate, or the generic acpi-cpufreq):
- performance — Runs the CPU at maximum frequency. Best for servers under sustained load.
- powersave — Runs at minimum frequency. Best for idle machines or battery-critical situations.
- ondemand — Scales up quickly on load, drops down when idle. Classic default for desktops.
- conservative — Like ondemand but ramps up more gradually. Gentler on power draw.
- schedutil — Hooks directly into the CPU scheduler. Generally the best balance for modern kernels (5.x+).
- userspace — Lets you set frequency manually. Useful for testing or locked frequencies.
Checking Available Governors on Your CPU
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
Intel systems running intel_pstate often only expose performance and powersave. That’s not a driver limitation — Intel’s implementation handles its own internal frequency stepping. AMD’s amd-pstate works the same way on newer CPUs.
cpufreq-utils vs cpupower
Two tools, same job, different history:
cpufreq-utilsprovidescpufreq-infoandcpufreq-set— older but widely availablecpupower(fromlinux-tools) is the modern replacement with broader feature support
Both work fine. Reach for cpupower when it’s available; fall back to cpufreq-set when it’s not.
Advanced Usage
Set Governor on All CPUs at Once
By default, cpupower frequency-set only affects CPU 0. To apply to all cores:
sudo cpupower -c all frequency-set -g performance
Or with cpufreq-set:
for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
echo performance | sudo tee $i
done
Set Frequency Limits Manually
You can pin a minimum or maximum frequency regardless of which governor is active:
# Set minimum frequency to 2.0 GHz
sudo cpupower frequency-set -d 2GHz
# Set maximum frequency cap to 3.0 GHz
sudo cpupower frequency-set -u 3GHz
Useful on laptops to cap heat output, or on shared servers to reserve headroom for other tenants. The governor still operates within those bounds — you’re just narrowing its range.
Monitor Real-Time Frequency Per Core
watch -n 1 "cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq"
Or a cleaner view:
cpupower monitor -m Mperf
Make the Governor Persistent Across Reboots
Governor changes via cpupower don’t survive a reboot. Two ways to fix that:
Ubuntu/Debian with cpufrequtils:
sudo nano /etc/default/cpufrequtils
GOVERNOR="performance"
sudo systemctl enable cpufrequtils
sudo systemctl restart cpufrequtils
Using systemd (distro-agnostic):
Create a one-shot service that runs at boot:
sudo nano /etc/systemd/system/cpugovernor.service
[Unit]
Description=Set CPU governor to performance
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/bin/cpupower -c all frequency-set -g performance
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now cpugovernor.service
Script: Auto-Switch Governor Based on Power Source (Laptop)
Want performance when plugged in and powersave on battery? Drop this into /usr/local/bin/cpu-governor-switch.sh:
#!/bin/bash
# /usr/local/bin/cpu-governor-switch.sh
POWER_STATUS=$(cat /sys/class/power_supply/AC/online 2>/dev/null || echo 1)
if [ "$POWER_STATUS" -eq 1 ]; then
cpupower -c all frequency-set -g performance
echo "AC connected — governor set to performance"
else
cpupower -c all frequency-set -g powersave
echo "On battery — governor set to powersave"
fi
chmod +x /usr/local/bin/cpu-governor-switch.sh
Hook it to udev power events or run it from a cron job every few minutes.
Practical Tips from Real Deployments
Servers: Always Check the Governor After Provisioning
On a production Ubuntu 22.04 server (Intel Core i5-8400, 6 cores, 4GB RAM), switching from powersave to performance cut AI content generation time from 45 seconds to around 28 seconds — a 38% improvement with zero code changes. The CPU had been artificially held back the entire time. The systemd service above kept the setting intact across reboots and kernel updates.
Fresh cloud VMs and bare-metal servers almost universally ship with powersave or ondemand. Check immediately after provisioning. It takes 30 seconds and is easy to miss.
Check for Turbo Boost
Even with the performance governor active, Turbo Boost can be independently disabled. Worth checking:
# Intel
cat /sys/devices/system/cpu/intel_pstate/no_turbo
# 0 = turbo enabled, 1 = turbo disabled
# Enable turbo boost
echo 0 | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
Thermal Throttling Isn’t Governor Throttling
CPU keeps dropping frequency even with the performance governor set? That’s thermal throttling — not the governor. Both look identical in monitoring tools, but the causes are completely different. Check:
dmesg | grep -i "cpu.*throttl"
cat /sys/class/thermal/thermal_zone*/temp
No amount of governor tuning fixes a cooling problem. Clean the heatsink first.
schedutil Is Worth Trying on Desktop/Laptop
Running acpi-cpufreq as your driver? (Check with cpupower frequency-info.) Then schedutil is often the best all-around governor — it reacts to load faster than ondemand and wastes less power than performance:
sudo cpupower -c all frequency-set -g schedutil
Quick Health Check Script
#!/bin/bash
echo "=== CPU Frequency Status ==="
echo "Driver: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver)"
echo "Governor: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)"
echo "Min freq: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq) kHz"
echo "Max freq: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq) kHz"
echo "Current freq:"
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq; do
echo " $(basename $(dirname $(dirname $cpu))): $(cat $cpu) kHz"
done
Run it after any governor change to confirm the setting applied across all cores. Save to /usr/local/bin/cpu-status and make it executable — two seconds to run, tells you everything at a glance.
Governor tuning is unglamorous work. But on CPU-bound workloads, the difference is measurable and immediate — and it costs five minutes. Check the governor before you spend hours profiling application code that isn’t the problem.

