Following the BoF on power consumption of software Cornelius chaired at Akademy 2020 I did look a bit into tooling for that, in particular for cheap ways to measure electrical power consumption. Here are the results so far.

Why measure electrical power consumption?

Our existing profiling tools for improving software performance implicitly also identify parts that presumably increase the power consumption, and we do have specialized tools like powertop that are good at identifying specific types of power drains. But not everything is visible in there, e.g. CPU/GPU trade-offs, or the actual effects of power management options or display settings.

So being able to measure the actual power consumption between the wall plug and the full device seems useful, to the very least to verify that assumptions we make from other profiling tools actually hold.

Requirements

Measuring electrical power isn’t exactly an unsolved problem, even if it’s not entirely trivial when looking at the combination of alternating current and switching power supplies. However, it’s not straightforward to find a solution when adding all our desired constraints:

  • Work with a wide range of devices to measure without requiring modifications, and covering the total power consumption, ideally something you just connect to the power plug and the wall socket.
  • High time resolution: Power consumption of computing hardware can change very very rapidly, averaging over a long time period might thus hide information relevant for us.
  • Cheap: To actually make an impact, I think we need to spread the equipment widely in the community, and that’s much more likely with tools that cost 10€ rather than a few k€.
  • Easy and safe to operate for people without an electrical engineering background: Same as the above, that should help spreading the tools widely.
  • Bonus: Machine readable measurement data. That could allow us to build further software tools on top of this, such as test automation or CI integration for checking for power regressions.

Finding a solution that covers some of those requirements isn’t particularly hard:

  • If you compromise on price, there’s beautiful professional equipment for this.
  • If you compromise on time resolution, there’s reasonably accurate devices sold for about 10€ in every hardware store as e.g. “energy monitor”, typically with a small LCD screen showing the accumulated electricity use over a period of time.
  • If you compromise on safety (or at least accept considerable effort to achieve safety), the necessary sensors to build a DIY measurement device only cost a few Euros.

Repurposing a Wifi power plug

While preparing the office at work for full remote operations earlier this year I came across a type of devices that seemed to check all those boxes though: A Wifi-controlled power plug capable of running a Free Software firmware and an integrated power sensor.

To try this I got myself a few Gosund SP111 for about 8€ a piece, and replaced their firmware with Tasmota. The manual flashing instructions might look a bit scary, but thanks to “opportunities” in their stock firmware this can also be done conveniently over the air using tuya-convert. Following the Docker-based approach in their instructions made this work on first try without any issues for me. Out of the box this was already showing power measurements in its web UI, with an update interval of a few seconds.

Picture of two Gosund SP111 Wifi power plugs and a screenshot of the Tasmota web interface running on it.
Gosund SP111 Wifi power plug and the Tasmota web interface running on it.

The initial values were not at all plausible though, going through the power calibration procedure helped with that. Reading out measurements automatically is possible via MQTT, so that’s covered as well.

At this point I was reading through the firmware code, assuming it would need adjustments to allow higher sample rates, but it turns out we can get this down to 200ms by just sending the right MQTT commands. The two following crude scripts running in parallel produce a CSV stream with the various measurement values.

mosquitto_pub -t "cmnd/tasmota/VoltRes" -m "3"
mosquitto_pub -t "cmnd/tasmota/AmpRes" -m "3"
mosquitto_pub -t "cmnd/tasmota/PowerRes" -m "5"

while true; do
    usleep 200000
    mosquitto_pub -t "cmnd/tasmota/STATUS" -m "10"
done

This sets the device to report measurements in the highest available resolution, and then polls in a 200ms interval. The results are received and unpacked by the next script. Its output is CSV that can be redirected as needed.

echo "Time;Voltage;Current;Power;Apparent Power;Reactive Power;Factor"

time=0
mosquitto_sub -t 'stat/tasmota/STATUS10' | while IFS= read -r line
do
    time=$((time+200))
    voltage=`echo $line | jq ".StatusSNS.ENERGY.Voltage"`
    current=`echo $line | jq ".StatusSNS.ENERGY.Current"`
    power=`echo $line | jq ".StatusSNS.ENERGY.Power"`
    apparent_power=`echo $line | jq ".StatusSNS.ENERGY.ApparentPower"`
    reactive_power=`echo $line | jq ".StatusSNS.ENERGY.ReactivePower"`
    power_factor=`echo $line | jq ".StatusSNS.ENERGY.Factor"`
    echo "$time;$voltage;$current;$power;$apparent_power;$reactive_power;$power_factor"
done

Visualizing measurements

There’s plenty of ways to process the CSV data, a real-time view turned out to be quite useful though. As the data can be rather noisy a basic smoothing filter also helps to make things easier to read.

KDE’s LabPlot can consume CSV “streams” and has the right filters for this. Unfortunately its filters cannot be applied in realtime yet, so the LapPlot team pointed me to a much older KDE application that can do this: Kst. It’s filters are frequency-based, so we need a low-pass filter to smooth the measurements. Not as nice as what LabPlot produces IMHO, but it gets the job done.

Observations

Good news first: This is sensitive enough to see the impact of simple user interactions, power saving options (ie. the Good/Bad toggles in powertop), display brightness changes, etc.

Plot of an example measurement showing power over time.
Example measurement (200ms sample interval, no filter): mouse cursor being moved between samples 100 and 150, with a peak while hovering a task bar entry.

How good this is, ie. how close the reported values get to reality, and to what extend the noise is inherent to the sensor I have no idea though, lacking a calibrated reference to compare this to. Based on suggestions found online on how to reduce the noise by hardware modifications I have to assume most of that is coming from the sensor.

Future Work

There’s plenty of things to further investigate here still, both regarding assessing and improving the quality and resolution of the measurements (e.g. by looking into increasing the sampling frequency by modifying the Tasmota firmware, assuming that is even useful), and regarding establishing the power impact of software settings or options.

While not doing work that we don’t need to do is of course better either way, there are many less obvious questions to investigate with this:

  • Can we enable more of the power management options exposed by powertop by default? There’s probably good reasons why they are off, but maybe that selection can be done more targeted? Or if it’s about user-decided trade-offs, maybe that can be made easier accessible for more users?
  • How do operations on the CPU and GPU compare, or different ways of accessing the GPU? Thinking about the various compositor settings here for example.
  • How do we best perform long-running background tasks? As fast as possible with all available resources, or stretched out over time?
  • Can we somehow make automatic screen brightness control more clever, e.g. by improving idle or presence detection?
  • Can we save power by making a dark color scheme the default on OLED screens?

And that’s just scratching the surface I guess.

As I didn’t break any of the Wifi power-plugs during these experiments, I still have two spares I can pass to anyone in the community interested in digging into this as well!