I’ve noticed that my Intel Xeon E3-1230 v2 CPU runs at the maximum frequency on my TrueNAS Core, even at a negligible load. This post describes how to configure the powerd daemon to shave off a few watts of idle power by allowing the frequencies to scale.

Observation

You can monitor the CPU frequency by watching the dev.cpu.0.freq state:

cmdwatch -n 1 sysctl dev.cpu.0.freq

Alternatively, run powerd -v in the elevated shell. If you go this route—stop the monitoring before proceeding; otherwise the actual service won’t start – it will think powerd is already running, which is not wrong.

You may notice the frequency is pegged at max all the time; this is what we are going to fix today.

Intervention

All you really need is read man powerd and enable the RC Tunable in the TrueNAS UI to configure the power management policy and launch the service at startup by adding the following two lines to /etc/rc.conf:

powerd_enable="YES"
powerd_flags="-b min -a adaptive -n adaptive"

This tells powerd to set performance to minimum when battery is connected, and to adaptive mode when on AC power, or when the power status is unknown.

Don’t directly edit the file, as the changes will be lost on restart; instead add the configuration under Tunables in the TrueNAS UI.

To add each variable, under System, Tunables click Add, input the variable name, value (sans quotes) into the appropriate boxes, select type rc.conf from the pull down, write some meaningful description, and keep Enabled flag on.

powerd rc tunables

These changes will take effect upon reboot. To start the service in the current session and avoid rebooting, configure and start the service manually this one time:

sysrc powerd_flags="-b min -a adaptive -n adaptive"
service powerd onestart

Verification

Revisit Observation and confirm that the clock is now being scaled properly.

Advanced configuration

Minimum and maximum frequencies

Read man powerd. Of interest are -m and -M flags that limit minimum and maximum frequencies to throttle to.

-M freq     Specifies the maximum frequency to throttle up to.
-m freq     Specifies the minimum frequency to throttle down to.

The supported frequency ranges of your CPU are reported in the dev.cpu.0.freq_levels state:

% sysctl dev.cpu.0.freq_levels | tr " " "\n"
dev.cpu.0.freq_levels:
3501/69000
3500/69000
3400/66169
3200/60660
3100/57982
3000/55354
2800/50893
2700/48405
2500/43573
2400/41238
2300/38941
2100/35071
2000/32906
1900/30787
1700/26690
1600/24705

Perhaps, adding -M 2400 to the powerd_flags would not be a bad idea?

Nice processes

Another useful flag worth considering is -N:

-N          Treat "nice" time as idle for the purpose of load
calculation; i.e., do not increase the CPU frequency if the
CPU is only busy with "nice" processes.

A note on high-core count systems

There is a unique behavior quirk with powerd on a high core counts systems: powerd seems to kick up all the clocks in adaptive mode under low total system load, which may still be a high number in absolute terms: e.g. 100% CPU usage on 50-core system is just 2%, and yet, powerd seemingly takes 100% at face value. And since it does not accept thresholds higher than 100%, that 2% load results in all clocks pegged at max—that’s quite an overreaction. And then there is question of what to do if a single core is 100% used while others are idle?

I’ve attempted to make sense of and work around its behavior and gave up, ultimately setting mode to min. This, however, capped NFS performance somewhat—so I needed a better solution.

What’s a powerdxx?

It is positioned as a drop-in replacement of powerd (not really, command line is not compatible) but it promises to address shortcomings of powerd, and in fact delivers. Namely:

  • it takes four samples by default, thus overreacting on surges less
  • it manages multicore systems correctly. Quoting the manual:

    Like with powerd(8), this means, that high load on a single core will cause an increase in the clock frequency. Unlike powerd(8) it also means that moderate load over all cores allows a decrease of the clock frequency.

Installing and configuring powerdxx on TrueNAS core

TrueNAS is an appliance, so we are not supposed to install anything there: not only newly added software may conflict with carefully cherri-picked existing system packages, but it will also get wiped on the system update.

But we are going to do so anyway, for three main reasons:

  • It is our NAS. We are going to do whatever the hell we want with it.
  • Powerdxx is a self-contained package, it does not have any conflicting with the core TrueNAS services dependencies.
  • TrueNAS Core is dead. There is not going to be any update to worry about.

To install the package, we need to let pkg download software from remote repository and then revert everything for safety:

# Turn off local repo and turn on FreeBSD repo:
sed -i .orig 's/enabled: yes/enabled: no/' /usr/local/etc/pkg/repos/local.conf
sed -i .orig 's/enabled: no/enabled: yes/' /usr/local/etc/pkg/repos/FreeBSD.conf

pkg install -y powerdxx

# Undo the above
sed -i .orig 's/enabled: b/enabled: no/' /usr/local/etc/pkg/repos/local.conf
sed -i .orig 's/enabled: no/enabled: yes/' /usr/local/etc/pkg/repos/FreeBSD.conf

Then go to Tunables and configure RC tunables as following:

powerdxx_enable="YES"
powerdxx_flags="-b adaptive"

Run it in interactive mode powerdxx -b adaptive -f in the shell. Play with the system load and watch it do its thing. Then to launch it immediately without rebooting the nas – powerdxx -b adaptive.

Persistence

After reboot, the package will disappear. To ensure it survives reboot, copy the powerxx related bits to some dataset, for example, tank/services/powerxx, like so:

/mnt/pool1/services/powerdxx/root/etc/local/rc.d/powerdxx
/mnt/pool1/services/powerdxx/root/usr/local/share/doc/powerdxx/refman.pdf
/mnt/pool1/services/powerdxx/root/usr/local/share/doc/powerdxx/README.md
/mnt/pool1/services/powerdxx/root/usr/local/sbin/powerdxx

and create a bootstraper script that will copy the stuff back to root, and start the service:

#!/bin/bash

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

cp -r "$SCRIPT_DIR/root/" "/"

sysrc powerdxx_flags='-n adaptive'

service powerdxx enable && service powerdxx start && service powerd stop

Call this script from TasksInit/Shutdown ScriptsSCRIPT | POSTINIT

History

Sep 16, 2023 initial publication
May 15, 2025 A note on powerdxx for high core count systems
Jun 8, 2025 A note on persistence for powerdxx