cpufreq and cpuidle
On this page
Low frequency does not equate to deep idle, and performance does not mean disabling idle. CPUFreq manages active performance, while CPUIdle manages idle states. When comparing, you must also distinguish between power, duration, and energy.
Drivers, attributes, and default policies depend on the kernel and hardware; rely on the actual policy and runtime state.
| Goal | Where to Look |
|---|---|
| Performance requests and hardware autonomy | CPUFreq, governor, schedutil, vendor modes |
| Idle and placement | CPUIdle, EAS |
| Evidence and comparison metrics | Read-only checks, energy comparison |
The Control Unit for CPUFreq is the Policy
The CPUFreq core manages the generic interface, the governor selects performance requests based on load and other information, and the driver interacts with the specific hardware. Some drivers can bypass the generic governor and provide their own control algorithms.
Multiple logical CPUs may share the same performance control interface, corresponding to the same cpufreq_policy. policyX in sysfs is a clearer unit of observation; reading cpuN/cpufreq individually may result in seeing the same policy multiple times. CPUFreq
Governor Names Must Be Interpreted in Context of the Driver
| Generic Governor | Primary Strategy | Conclusions You Should Not Draw |
|---|---|---|
| performance | Requests the highest frequency allowed by the policy | Always reaches the highest measured frequency, zero latency |
| powersave | Requests the lowest frequency allowed by the policy | The total energy consumed for the entire workload is definitely minimized |
| schedutil | Uses signals like utilization provided by the scheduler | Runs only on ticks, looks only at a single CFS counter |
| ondemand | Adjusts based on utilization sampling | Performs worse than other strategies in all scenarios |
| conservative | Adjusts requests more gradually | Can ignore driver transition latency and workload characteristics |
Frequency requests are constrained by policy upper and lower limits; actual execution is also affected by temperature, power budgets, and hardware autonomy. scaling_cur_freq often reflects the driver's last request or an architecture-provided estimate, not necessarily the real clock speed at the exact moment the file is read.
Why schedutil is Close to the Scheduler
Events such as task enqueueing, dequeuing, and periodic updates trigger utilization updates, not just on every scheduler tick. Frequency invariance information, capacity, RT/DL load, I/O wait boost, utilization limits, and update throttling may all participate in the actual execution path.
The utilization-proportional formula in the documentation helps understand the target: the closer the load is to capacity, the higher the request. However, it is not precise pseudocode that covers the entire implementation. If the driver supports fast switching, it can update directly; otherwise, it may complete via other execution contexts. The source entry point is kernel/sched/cpufreq_schedutil.c.
Hardware Autonomy Modes for Intel and AMD
The active mode of intel_pstate provides its own performance/powersave algorithm. When HWP (Hardware Power Management) is available, it allows the hardware to select performance within the requested range and preferences. Here, powersave does not equal the generic powersave fixed request for the lowest frequency. The passive mode usually appears as intel_cpufreq in the scaling driver, with requests issued by the generic governor. intel_pstate
amd-pstate is based on the CPPC performance interface, and its capabilities depend on the processor, firmware, and configuration. The differences between passive, active, and guided lie in how software and hardware share the responsibility for performance selection; active often involves EPP (Energy Performance Preference) preferences, while guided allows hardware to participate in selection within a given range. You cannot assume that every machine enables the same mode just because it is "Zen2+". amd-pstate
CPUIdle: Residency Benefits vs. Wake-up Costs
The idle governor selects from driver-provided idle states based on predicted idle duration, the next timer event, and latency constraints. Two important parameters are the exit latency and the target residency time worth entering that state for.
Assume an idle state has a target residency of 100 μs and an exit latency of 20 μs:
| Condition | Why Entering Might Be Unsuitable |
|---|---|
| Predicted idle is only 30 μs | Too short; may not gain sufficient residency benefit |
| Latency constraint is max 5 μs | 20 μs exit latency does not satisfy the constraint |
Even if the predicted idle time is long, you cannot ignore wake-up latency. These are model parameters, not unified metrics for a specific C-state level.
Names like C1, C6, actual power actions, and latencies vary by platform. Core and package states also differ: a core requesting deep idle does not mean the shared power domain will immediately power down. You should read the state and actual residency statistics exposed by the driver, rather than memorizing a fixed microsecond table. CPUIdle
menu and TEO use different prediction and feedback strategies. Which one is enabled and which performs better depends on configuration and workload; there is no single default winner that is always more accurate.
Filtering Candidate States with Two Constraints
Placing predicted idle duration and allowed exit latency on two independent axes allows you to explain "why a shallow state is still selected despite a long idle period." Below are four hypothetical states, with depth order used only for this example.
| State | Target Residency μs | Exit Latency μs |
|---|---|---|
| poll | 0 | 0 |
| shallow | 10 | 2 |
| deep | 100 | 20 |
| deeper | 1000 | 100 |
=
assert >= 0 and >= 0
=
return
assert == # Time too short, deep states yield insufficient benefit
assert == # Time sufficient, but exit latency exceeds limit
assert ==
assert == # Both boundaries satisfied
assert ==
assert ==
This code only demonstrates the intersection of constraints, not the implementation of menu or TEO. Real governors also handle state disabling, historical feedback, timers, and ticks; asynchronous interrupts may also arrive before the predicted duration ends. A target residency of 100 μs does not mean the hardware promises to sleep for at least 100 μs, nor does it justify delaying the handling of real wake-up events. CPUIdle: Target Residency and Exit Latency
Change predicted idle duration and permitted exit latency. Eligible states are then compared by total energy, including transition cost.
First require sufficient target residency and an allowed exit latency, then compare total energy. C is this model’s transition-energy cost, not a universal Linux-governor scoring formula.
Target residency indicates whether entry is worthwhile; exit latency must also meet QoS. A long idle prediction does not override a strict wakeup-latency limit.
EAS is Energy Estimation for Task Placement
Energy Aware Scheduling uses information like the Energy Model to compare the energy impact of task placement, especially involving CPUs with asymmetric capacity. It relates to utilization estimation and performance scaling, but it does not merge cpuidle and cpufreq into a single unified decision, nor can it be simplified as always preferring already-woken CPUs. EAS
Under overload, missing models, or when enabling conditions are not met, you cannot assume EAS is active. When understanding across architectures, focus on the model and scheduling conditions, rather than just treating it as an ARM-specific switch.
Read-Only Checks on the Current Machine
The following uses Python to iterate over existing sysfs attributes, avoiding false positives where missing fields in different drivers are mistaken for errors:
=
= /
= /
Frequency attributes are typically in kHz; idle latency/residency/time interfaces are typically in microseconds; usage is the cumulative entry count. Statistics should compare increments over a period, not treat cumulative values since boot as current percentages. Capabilities visible in containers or VMs may differ from the physical host.
Compare Strategies by Looking at Both Time and Energy
Power is the instantaneous consumption rate; energy is the integral of power over time. Lower power but longer work duration does not necessarily mean less energy consumed; finishing faster and entering idle is not necessarily optimal for all loads. At least compare throughput or completion time, tail latency, energy, and temperature, while keeping tasks, background load, and measurement scope consistent.
Within the Same 100 ms Window, Fast Completion vs. Low Power Results May Invert
Assume the same amount of work is completed every 100 ms, measuring the same power domain, with constant active and idle power within each segment. Ignoring switching energy, idle power is uniformly 1 W:
| Scheme | Active Phase | Remaining Idle Phase | Total Energy per Cycle |
|---|---|---|---|
| Fast Completion | 10 W × 20 ms | 1 W × 80 ms | 0.28 J |
| Lower Active Power | 6 W × 50 ms | 1 W × 50 ms | 0.35 J |
| Higher Active Efficiency | 4 W × 50 ms | 1 W × 50 ms | 0.25 J |
The second row has lower active power but runs longer, resulting in higher cycle energy; the third row wins by further reducing active power. Therefore, both race-to-idle and frequency downscaling require measurement support; you cannot deduce the answer from the strategy name alone. If the completion deadline is 40 ms, the latter two rows do not meet the time limit for this task, even if their energy is lower.
assert 0 <= <=
return
=
=
=
assert ==
assert < <
assert / == # Average power per cycle 2.8 W
assert 20 <= 40 < 50
Actual testing must also confirm that the amount of work completed twice is the same, and record whether frequency changes actually affect the bottleneck. For example, tasks waiting for memory or I/O may not accelerate proportionally with core frequency; longer idle times may not necessarily allow the package to enter deeper states. When background work exists, you should report the total energy of the measurement domain and the baseline handling method simultaneously; you cannot attribute all whole-machine background changes solely to the governor.
Measurement Scope: Power Domain Energy Does Not Equal Socket/Whole-System Power Consumption
RAPL and other counters reflect the energy of specific power domains, not the whole-system power consumption at the socket; counters also wrap around. For further distinction between whole-system sleep and single-device runtime PM, see Suspend and Resume.
Converting Cumulative Counts to Interval Metrics
If for the same idle state, within a 2-second observation interval, time increases by 500,000 μs and usage increases by 200, then the software-accounted residency proportion is 25%, and the average accounted duration per entry is 2,500 μs. This is only an interval statistic for that CPU and that state; directly summing the proportions of four CPUs will not yield a percentage meaningful for a single CPU. Software statistics for driver-requested states do not necessarily equate to hardware package actual residency counts.
For energy counters, you first calculate the difference, then divide by the elapsed time. For counters that wrap around within range R and have not been reset, (after - before) % R can calculate the increment modulo R; you can only treat it as the actual energy difference if you know the true growth is less than R. When the interval is too long, even if the later value is greater than the earlier one, it may have already wrapped around a full cycle.
assert 500_000 / 2_000_000 == 0.25
assert 500_000 / 200 == 2500
, , = 1000, 950, 30
= %
assert == 80
assert % ==
assert % == # Same reading may also correspond to multiple cycles
The units for energy_uj and max_energy_range_uj are μJ; the specific zone read determines the statistical scope. Parent and child zones may cover overlapping hardware; you cannot default to summing the package and all its sub-domain energies as the total. Sampling interval, wrap-around range, counter reset, and domain names should be preserved with the results. Powercap Interface