Why CPU Frequency Scaling Matters in a Homelab
Your homelab server runs 24/7. Every watt it draws adds up over a year — at $0.12/kWh, a 100W difference costs about $105 annually. But power is not the only consideration. A Proxmox host running a DNS resolver, a reverse proxy, and a database needs different CPU behavior than a gaming rig or a CI build runner.
Linux’s CPUFreq subsystem controls the processor’s clock speed and voltage dynamically. By tuning frequency scaling governors, p-state drivers, Turbo Boost behavior, and idle states (C-states), you can shift your server’s power profile from “full blast always” to “responsive but efficient” without touching hardware.
This guide covers every layer: checking your current configuration, choosing the right governor, tuning Intel and AMD drivers, controlling Turbo Boost, managing C-states, and applying profiles for common homelab workloads.
Checking Your Current CPU Governor and Frequency
Before making changes, inspect your system’s current CPUFreq configuration. The cpupower utility from the linux-cpupower package is the primary tool.
|
|
The output shows the driver in use (intel_pstate, intel_cpufreq, acpi-cpufreq, or amd_pstate_epp), the available governors, the current policy, and the hardware frequency limits.
|
|
The driver matters: intel_pstate and amd_pstate_epp handle frequency selection in hardware with software hints, while acpi-cpufreq and intel_cpufreq use software-level ACPI tables. This distinction determines which tuning knobs are available.
Available CPU Governors Explained
Linux provides several frequency governors, each with a different strategy for balancing performance and power.
| Governor | Behavior | Best For |
|---|---|---|
| performance | Maximum frequency always | Latency-sensitive workloads (databases, real-time audio) |
| powersave | Minimum frequency always | Maximum power savings, very low load servers |
| ondemand | Scales up on CPU load, scales down when idle | General purpose, older kernels only |
| conservative | Like ondemand but smoother ramp | Systems sensitive to frequency transitions |
| schedutil | Scheduler-driven, uses Per-Entity Load Tracking | Modern default, balanced performance/power |
schedutil is the default on most modern Linux distributions with kernel 5.4+. It integrates directly with the scheduler and provides the best balance across varied workloads. The scheduler knows exactly what each task needs, so frequency decisions are made with full context.
ondemand and conservative are legacy governors. On modern hardware with intel_pstate or amd_pstate_epp active, the p-state driver’s hardware control outperforms any software governor. Always prefer the driver’s hardware-governed modes when available.
|
|
Configuring the Governor with cpupower
Set the governor persistently with a systemd service or the distro-specific configuration file.
|
|
To make the change persistent across reboots, create a systemd oneshot service:
|
|
|
|
On Debian and Ubuntu, you can instead edit /etc/default/cpupower and set GOVERNOR="schedutil", then enable the cpupower service if the package ships one. This approach varies by distribution, so check your local init scripts first.
Intel P-State and AMD P-State Driver Tuning
The p-state drivers expose hardware-level performance controls that go beyond simple governor selection.
Intel P-State (intel_pstate)
intel_pstate operates in two modes:
- Active mode (default on Intel Core i3/i5/i7/i9): The hardware manages P-states internally, and the CPUFreq governor acts as a hint. The governor selection mostly affects Energy Performance Bias (EPB).
- Passive mode (
intel_pstate=passivekernel parameter): The driver behaves likeintel_cpufreq, and software governors have full control. Useful for custom frequency policies.
|
|
When Hardware-Managed P-States (HWP) are enabled — common on Skylake and newer — the x86_energy_perf_policy utility provides a higher-level hint:
|
|
EPB values range from 0 (performance) to 15 (power save). The hardware uses this hint to decide when to enter higher P-states (higher frequency) or lower ones.
AMD P-State (amd_pstate_epp)
AMD’s equivalent uses Energy Performance Preference (EPP), exposed through sysfs:
|
|
On AMD Ryzen and EPYC systems running kernel 6.3+, amd_pstate_epp is the default driver and provides the best balance of responsiveness and power efficiency.
Turbo Boost Control
Turbo Boost (Intel Turbo Boost / AMD Precision Boost) allows cores to exceed their base frequency when thermal and power headroom allows. This delivers snappy burst performance but increases peak power draw and heat.
|
|
The no_turbo sysfs knob applies to both Intel and AMD systems using their respective p-state drivers. For acpi-cpufreq users, the control is at cat /sys/devices/system/cpu/cpufreq/boost.
Disabling Turbo Boost is useful when:
- Running in a small form factor case with limited cooling
- Running latency-sensitive workloads where frequency variability hurts predictability
- Prioritizing power efficiency over peak performance — disabling turbo typically reduces peak power by 15-30% while only reducing peak throughput by 10-20%
Make the setting persistent with a sysfs.d drop-in:
|
|
Or use a systemd tmpfiles.d rule:
|
|
CPU Idle States (C-States) Configuration
Modern processors have multiple idle states, ranging from C0 (active) through C1 (halt), C1E (enhanced halt), C6 (deep sleep with cache flush), up to C10 (package-level deep sleep).
|
|
Deeper C-states save more power but add wake latency. C1 wake takes ~1 µs, while C6 wake can take 100+ µs. For a Proxmox host running VMs with real-time workloads, 100 µs wake latency can cause timing issues. For a general purpose Docker host, deeper C-states save meaningful power — often 5-15W on an idle server.
|
|
To apply permanently, add the kernel parameters:
|
|
Tradeoff: disabling deep C-states costs 5-15W at idle but guarantees sub-10 µs wake latency, essential for real-time containers or Proxmox with latency-sensitive VMs.
Practical Homelab Scenarios
Different workloads need different power profiles. Here are three common homelab configurations.
Scenario 1: Low-Power Proxmox Host (24/7)
An always-on server running lightweight containers and a few VMs.
|
|
Scenario 2: Database or Latency-Sensitive Server
A PostgreSQL or low-latency application host where consistent response times matter.
|
|
Scenario 3: Media or File Server
A server running Plex, Jellyfin, or Samba/NFS with bursty workloads and long idle periods.
|
|
Quick Profile Switching Script
Save this as /usr/local/bin/cpu-profile for on-the-fly switching between power profiles:
|
|
Make it executable and test:
|
|
Measuring Your Changes
Use these tools to verify the actual impact of your tuning:
|
|
turbostat reads the CPU’s built-in RAPL (Running Average Power Limit) counters and provides package-level power draw. powerstat runs a longer test and gives you min/max/avg after sampling.
Conclusion
CPU frequency scaling and power management are free tuning knobs that every homelab admin should understand. The defaults work, but they favor performance over efficiency or vice versa depending on your distribution. By selecting the right governor, tuning your p-state driver, deciding on Turbo Boost, and setting the appropriate C-state ceiling, you can shave watts off your power bill or microseconds off your latency — or find the balance that suits your workload.
Start with schedutil and default C-states (most balanced). If you run latency-critical services, move to performance with Turbo and deep C-states disabled. If you prioritize power efficiency, use schedutil with Turbo enabled and let the deeper C-states save you money at idle.
For further reading, see the Linux kernel documentation on CPUFreq at Documentation/admin-guide/pm/, or run cpupower help for all available subcommands.