Skip to content

Instantly share code, notes, and snippets.

@linnaea
Last active December 28, 2018 15:11
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 linnaea/6ab06de2f2d3b44ace4684bcbbfcc9ec to your computer and use it in GitHub Desktop.
Save linnaea/6ab06de2f2d3b44ace4684bcbbfcc9ec to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from os import listdir
from time import time, sleep
from math import log10, copysign
from typing import List
energy = dict()
si_prefix = 'M', 'k', '', 'm', 'u'
hsign = lambda x: copysign(0.5, x)
def stat_energy(domain: str, readout: int, rollover: int) -> int:
now = time()
if domain not in energy:
energy[domain] = readout, readout, now
return 0, readout
last_read, total, last_time = energy[domain]
diff = readout - last_read
if diff < 0:
diff += rollover
total += diff
power = diff / (now - last_time)
energy[domain] = readout, total, now
return power, total
def read_file(path: str) -> str:
with open(path) as file:
return file.read().strip()
def bool_enabled_disabled(v) -> str:
return "Enabled" if v else "Disabled"
def fmt_numeric(v_u: int, width: int=4) -> str:
if not v_u:
return '0.' + '0' * (width - 2) + ' '
sii = len(si_prefix) - 1
while log10(abs(v_u)) >= (width + hsign(v_u) - 0.5) and sii > 0:
v_u /= 1000
sii -= 1
v = str(int(v_u))
decimals = width - 1 - len(v)
if decimals > 0:
v = str(round(v_u, decimals))
while len(v) < width:
if decimals > 0:
v += '0'
else:
v = ' ' + v
return f"{v} {si_prefix[sii]}"
def print_rapl_dir(path: str, domain: List[str]):
indent = " " * max(0, len(domain) - 1)
dom_id = ":".join(domain)
dom_prefix = "intel-rapl:" + dom_id + (":" if dom_id else "")
entries = listdir(path)
if 'name' in entries:
dom_name = read_file(f"{path}/name")
dom_enabled = int(read_file(f"{path}/enabled"))
print(f"{indent}Domain #{dom_id} {dom_name}: {bool_enabled_disabled(dom_enabled)}")
energy_readout = int(read_file(f"{path}/energy_uj"))
energy_range = int(read_file(f"{path}/max_energy_range_uj"))
power, total = stat_energy(dom_id, energy_readout, energy_range)
print(f"{indent} Power Statistics:")
print(f"{indent} Average power: {fmt_numeric(power)}W")
print(f"{indent} Total consumption: {fmt_numeric(total / 3600)}Wh")
print(f"{indent} Counter rollover: {fmt_numeric(energy_range / 3600)}Wh")
print("")
for ent in entries:
if not ent.startswith('constraint_') or not ent.endswith('_name'):
continue
i = ent[11:-5]
const_name = read_file(f"{path}/constraint_{i}_name")
try:
max_power = int(read_file(f"{path}/constraint_{i}_max_power_uw"))
except OSError:
max_power = 0
power_limit = int(read_file(f"{path}/constraint_{i}_power_limit_uw"))
if not max_power and not power_limit:
continue
time_window = int(read_file(f"{path}/constraint_{i}_time_window_us"))
print(f"{indent} Constraint {i}: {const_name}")
print(f"{indent} Power Limit: {fmt_numeric(power_limit)}W", end="")
if max_power and max_power != power_limit:
print(f" (max: {fmt_numeric(max_power)}W)", end="")
print("")
print(f"{indent} Sampling Window: {fmt_numeric(time_window)}s")
print("")
subdomains = sorted(ent[len(dom_prefix):] for ent in entries if ent.startswith(dom_prefix))
if subdomains:
if 'name' in entries:
print(f"{indent} Sub-domains: {len(subdomains)}")
else:
print(f"Domains: {len(subdomains)}")
for subdomain in subdomains:
print_rapl_dir(f"{path}/{dom_prefix}{subdomain}", domain + [subdomain])
while True:
print('\033c', end="")
print_rapl_dir("/sys/devices/virtual/powercap/intel-rapl", [])
sleep(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment