While not that, this might be a poor person’s substitute for a TDP limit - a straight up perf limit. You’d lose the ability to go fast for brief periods of time but it should be similar for prolonged operation.
Thanks for sharing this! I spent just a little bit of time today playing with some system settings. I’m sad to say that I don’t have a complete answer to my original question of how well the powercap framework works, since I was a little perplexed by what turned out to be the tlp defaults. Those of you familiar with intel_pstate
, CPUFreq
, and powercap
will already know everything that I will report here, but novice Linux enthusiasts with a mere 10 years of usage like me may learn something
TLDR: I activated the defaults in tlp without realizing that these defaults create strict frequency limits for each threaded process. The good news is, I seemed to get powercap
working on my machine. Because of some technicalities, I’m unable to provide a meaningful report on the improvements it provides upon standard tlp.
My stress test and some reading
The Phenomenon
I started out by installing stress-ng
and trying to get baseline power statistics with powertop under both a single-core and multicore stress test. To my surprise, I found that the usage did not go above ~12w under these the 6 threaded test, and not above ~10w on the single-core test. I found this baffling since I did not set a percentage limit on max performance, and I’m using the 1135g7 which has a tdp of 28w.
I dug into my settings and confirmed that I did not set the max performance limiting. Yet, when I ran tlp-stat, I was informed that a 50% performance limit was being set.
# reported from tlp-stat
/sys/devices/system/cpu/intel_pstate/min_perf_pct = 9 [%]
/sys/devices/system/cpu/intel_pstate/max_perf_pct = 50 [%]
/sys/devices/system/cpu/intel_pstate/no_turbo = 0
/sys/devices/system/cpu/intel_pstate/turbo_pct = 47 [%]
/sys/devices/system/cpu/intel_pstate/num_pstates = 39
# i.e. the second line is equivalently this config:
CPU_MAX_PERF_ON_BAT=50
This seemed to explain why the frequency chart on powertop was not reporting above 1.8GHz for any core throughout either a single or multicore stress test.
Intel P-states
At this point, I wanted to know a bit more about what this intel_pstate thing is doing and how it differs from powercap. Here’s what I found:
…the CPUFreq core uses frequencies for identifying operating performance points of CPUs and frequencies are involved in the user space interface exposed by it, so intel_pstate maps its internal representation of P-states to frequencies too…
So pstate is a fancy version of capping CPU frequency—got it! Further:
Since the hardware P-state selection interface used by
intel_pstate
is available at the logical CPU level, the driver always works with individual CPUs. Consequently, ifintel_pstate
is in use, everyCPUFreq
policy object corresponds to one logical CPU andCPUFreq
policies are effectively equivalent to CPUs.
Integrating this quote with what we saw previously, here is what I can surmise.
Tlp by default implements pstate-based CPU frequency limiting. Since this limiting is applied to logical CPUs, this ensures that every thread running on the Framework is running at a capped frequency. Consequently, features like turbo boost and even short term boosts in processing are disabled under battery.
Of course, this does provide power advantages, but at the same time it would be nice if I could let one or two threads go above their pstate limit if it still meant having a relatively low power consumption. This means pesky user applications which use way too many CPU cycles (cough Zoom cough) could continue their decadent reign without impacting the user experience.
Researching Powercap
I found this page on the Linux kernel powercap implementation:
[In an example given on the page, t]here is one control type called intel-rapl which contains two power zones, intel-rapl:0 and intel-rapl:1, representing CPU packages. Each of these power zones contains two subzones, intel-rapl:j:0 and intel-rapl:j:1 (j = 0, 1), representing the “core” and the “uncore” parts of the given CPU package, respectively. All of the zones and subzones contain energy monitoring attributes (energy_uj, max_energy_range_uj) and constraint attributes (constraint_*) allowing controls to be applied (the constraints in the ‘package’ power zones apply to the whole CPU packages and the subzone constraints only apply to the respective parts of the given package individually).
From this quote, we may infer that constraints in the powercap framework are applied to the entirety of the CPU. Further, these constraints are a little more dynamic, since they apply to running averages over time rather than instantaneous limits like pstates:
Depending on different power zones, the Intel RAPL technology allows one or multiple constraints like short term, long term and peak power, with different time windows to be applied to each power zone.
So it seems like the application of powercap would allow me to set a similar limit on power usage, e.g. the 12w that I noticed on multicore workloads, without limiting performance on single-core workloads. E.g. no stuttering when launching a big app, container or VM, which might scale up and down quickly without triggering a powercap constraint. In terms of my benchmarks, I would expect this to allow the single-core stress test to go beyond its 1.8GHz limit under tlp while still limiting the multicore stress test.
What I tried
Without messing with the power-prioritizing governor, I tried simply removing the limit on pstate by adding:
CPU_MAX_PERF_ON_BAT=100
Then, I set a TDP target with the powercap-set
command:
sudo systemctl stop thermald
sudo powercap-set -p intel-rapl --zone=0 --constraint=0 -l 14000000 -s 10000000
# I had to add this to enable the "core" components of the CPU package
sudo powercap-set -p intel-rapl --zone=0:0 -e 1
I’m essentially using what was reported in the other thread on powercap, linked in my original post. I liked the idea of pinning to the 14W target as the 10-second running average, since this was close to what I got under the default tlp setting of limiting the pstate and @jbch settled on it after their own testing. It seems like powercap goes all the way down to 12W based on the intel specs for the i5 1135g7, although I haven’t tried putting this even lower. I verified that the system accepted these settings with sudo powercap-info -p intel-rapl
.
I also played a bit with the energy policy while using the powercap setting:
CPU_ENERGY_PERF_POLICY_ON_BAT=balance_performance
Interestingly, it did seem to have an impact on the metrics for the benchmark, even though the power draw was still limited by powercap. I.e., it seems like powercap might be “smarter” than this energy policy. More tests might be needed to confirm this, though.
What I haven’t done
I haven’t created the systemd scripts to make this setting stick, nor have I verified my conjectures about single-threaded workloads. I’d have to figure out how to get the stress test to “pin” to a specified core, and that’s just a bridge too far for one evening. For the moment, I’m going to give the laptop back to my wife without messing up her battery life, which is already completely amazing to her as it is!
You might have noticed that tlp by default also limits the turbo boost pstate to 47%. It would be interesting to see if I could uncap that as well in combination to gain more performance improvements on battery.
Conclusion
I hope this helps someone out there who is tinkering with their system, or who is trying to figure out how to use Intel’s “TDP-down” configuration in Linux. Let me know if my understanding is wrong, since I may have missed something in my sleuthing! I welcome any thoughts about how to measure CPU frequency under stress testing.
I thought that ~5hours was ok, but now I realized that I should expect something like 10hours.
I did all that was posted here and in other posts on this forum and I cannot get below C3 on idle. The lowest power I managed was ~9W.
I installed powertop and optimized and tlp including PCIE_ASPM_ON_BAT=powersupersave.
OS: KDE neon User - 5.24 x86_64
Kernel: 5.13.0-40-generic
Blacklisting unused SSD expansion cards to save ~1.4W and hit C10
After following all the guides around here, my power consuption was around 5.1 W idle and I only hit C9 but never C10. I found out, that my storage expansion card draws around 1.4W and prevented me from C10. I only use my SSD card to boot Windows, so I decided to blacklist it in my arch install. There is what I did.
This will make your storage card unavailable in your current linux install until you undo this.
1. Find the vendor and product IDs for the card.
~ ❯❯❯ lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 27c6:609c Shenzhen Goodix Technology Co.,Ltd. Goodix USB2.0 MISC
Bus 003 Device 003: ID 8087:0032 Intel Corp. AX210 Bluetooth
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 13fe:6500 Kingston Technology Company Inc. USB DISK 3.2
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
We are looking for the ID “13fe:6500”. (Maybe it’s the same for all cards, but please double check.)
2. Create a udev rule to blacklist the device
Change idVendor
to the first part of “13fe:6500” and idProduct
to the second part.
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="13fe", ATTRS{idProduct}=="6500", ATTR{authorized}="0"' | sudo tee /etc/udev/rules.d/01-expansion-ssd.rules
3. Reboot
4. Verifying
Run sudo fdisk -l
. The drive should not be listed anymore.
Check powertop. You should now see a lower power usage of around 1.4W and also C10.
Undo
Just remove the udev file and reboot.
sudo rm -f /etc/udev/rules.d/01-expansion-ssd.rules
Thank you for this! I usually keep my expansion cards removed, but it would sometimes be nice to have them installed (e.g. when I’m traveling and just might need USB-A). I worry about losing them if I keep them stored outside the laptop.
I think this is important for the tutorial.
I had a looooooot of problems with BIOS 3.06 and that stupid 92HD95B audio codec.
What does the “Boot performance mode” setting do in the BIOS? There’s an option for “Max battery.” Could that help?
Reasonably sure that controls the power state in BIOS?
Should that affect battery life? I could have been imagining things, but it seemed like my power usage was down after turning that on.
You’re imagining things, system overrides it shortly afterwards.
[ 0.087028] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
Yeah, I imagined it might be placebo. Do you know if setting the battery charge limit would help? I’m guessing it would with long term battery health.
My understanding is that controls how the system runs while booting, right up until it turns control over to the OS.
Has anyone compared tlp and auto-cpufreq? I’ve seen from a reddit thread that auto-cpufreq is actually better. I installed it and removed tlp and seem to be getting lower power consumption.
Sorry for the late response, I don’t frequent the Framework forums. Charge limits ruin runtime, but improve longevity.
Anyone tried using something like this to configure TDP instead?
The GPU rendering tips for Firefox (Linux battery life tuning) may be out of date for Firefox 100, at least, according to the linked Arch wiki page (Firefox - ArchWiki).
Hi guys
I got my Framework with i7-1165G7 a few weeks ago. I am running Fedora 36 and was optimizing battery life by replacing PPD with TLP 1.5 (powertop is just used for monitoring).
Configuring TLP with the setting
PCIE_ASPM_ON_BAT=powersupersave
brought idle power consumption down to 2.7W without further tweaks (C8/C10 is entered).
Now I get constant audio crackle (like playing some dusty vinyl) during music playback using headphones or internal speakers running on battery. Putting more load with background applications to the system reduces the crackling. Setting the parameter SOUND_POWER_SAVE_ON_BAT to 0/1/10 has no effect but configuring TLP to
PCIE_ASPM_ON_BAT=performance
removes the audio crackling immediately as well as setting RUMTIME_PM_ON_BAT to on from auto:
PCIE_ASPM_ON_BAT=powersupersave
RUMTIME_PM_ON_BAT = on
I think these settings block the system to enter higher C-states resulting in few watt higher power consumption. Any ideas how to solve this? Now I have to trade battery life for audio quality.
Thanks!
THIS IS VERY VERY VERY IMPORTANT
I WOULD HAVE SAVED DAYS OF WORK IF I WOULD KNOW ABOUT THAT
PLEASE PUT THIS INTO TUTORIAL
https://wiki.archlinux.org/title/Power_management#PulseAudio
I just found out that the audio codec is fine, the CPU is fine and PulseAudio is a reason for all my troubles with audio and power saving. Because PulseAudio doesn’t go to sleep by default, it keeps the audio codec awake and the codec keeps the CPU in high C states, and all of that wastes ~6W of power.
But I was f* reverse engineering an issue. From CPU through codec to PulseAudio.
And as always, the answer was in Arch wiki.
What about Pipewire? According to other posts, it should be using less power even during usage.
Pulse is pre-installed on my distro and I am using PulseEffects to make eq profiles for my headphones and stuff. I am not sure weather there is equivalent of PulseEffects for Pipewire and I am sure that I don’t want to go through setting it up again.
Also Pulse works now, so if it ain’t broke don’t fix it.