Skip to content

Instantly share code, notes, and snippets.

@dreness
Created November 20, 2023 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dreness/1c5117dd2d185dfbeed1f970213b6dc7 to your computer and use it in GitHub Desktop.
Save dreness/1c5117dd2d185dfbeed1f970213b6dc7 to your computer and use it in GitHub Desktop.
Extract just one data point from powermetrics, suitable for graphing
#!python -u
import subprocess
import plistlib
import sys
"""
Print selected power metrics from /usr/bin/powermetrics at intervals, suitable
for graphing.
"""
# available data is determined by which categories we ask for (the -s option)
interval = sys.argv[1] if len(sys.argv) > 1 else 1000
cmd = f"sudo powermetrics -i {interval} -s cpu_power --format plist"
# Execute the long-running command, which produces one plist to stdout every
# interval, spread across multiple lines.
# For each line of output from `powermetrics`:
# - accumulate lines into a bytearray
# When "</plist>" is seen:
# - parse the accumulated bytearray into a plist
# - print the combined power consumption
# - clear the bytearray
pl = bytearray()
# using shell mode here because we need sudo for powermetrics
for line in subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout:
pl.extend(line)
# look for the plist close tag
if "</plist>" in str(line):
# powermetrics adds a null byte at the start of each plist after the
# first, which breaks the plist parser. Remove it.
if pl[0] == 0:
pl = pl[1:]
d = plistlib.loads(pl[0:])
print(d.get('processor').get('combined_power'))
#print(d.get('all_tasks').get('cputime_ms_per_s')) # requires "all_tasks" category
pl = bytearray()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment