Linux CPU Frequency Scaling with cpupower and cpufreq-utils: Boost Performance and Save Power

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

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-utils provides cpufreq-info and cpufreq-set — older but widely available
  • cpupower (from linux-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.

Share: