01 / COUNTERS
Direct RAPL reads
Dynamically discovers powercap domains and handles counter wraps using each domain's reported range.
← Back to overviewWhat it is
RAPL is a set of hardware energy counters exposed by the Linux kernel through the powercap interface. A reading is cumulative: it tells you how much energy a domain has used since its counter began, not the energy of one process by itself.
DoL8 reads before and after a target, then computes the difference. A package domain can represent the processor package; nested domains may report core, uncore, or DRAM energy when the CPU and firmware expose them.
Why it matters
Elapsed time alone cannot show whether a workload used more or less energy. Reading the hardware counter at both ends gives a repeatable machine-level estimate in joules, without pretending that the processor can isolate a process perfectly.
Powercap layouts vary by kernel and CPU. Discovering domains rather than assuming one fixed directory keeps the tool useful across systems and lets it report unavailable hardware clearly.
How it works
The Linux interface commonly places package directories under /sys/class/powercap/intel-rapl:*; child names such as intel-rapl:0:0 may expose subdomains. Each usable directory has a name, energy_uj, and max_energy_range_uj. The last file defines the counter's wrap range.
For a single wrap, the delta in microjoules is current - previous when the counter increased, otherwise (range - previous) + current. Divide by 1,000,000 for joules; divide that delta by elapsed seconds for average watts. DoL8 avoids double-counting nested domains by preferring package energy for its total when available.
if current >= previous:
delta_uj = current - previous
else:
delta_uj = max_energy_range_uj - previous + current
energy_j = delta_uj / 1_000_000
average_w = energy_j / elapsed_secondsDoL8's reader recursively discovers RAPL-named directories and validates non-negative readings and positive ranges. It uses the reported range for wrap correction; it cannot infer multiple wraps that occur between two reads.
What to build
- Discover domains. In
dol8/rapl.py, walk the powercap root, require readable name, energy, and range files, and normalize domain names without assuming a single package. - Keep reads paired. Capture per-domain starting counters and ranges, run the measurement interval, then read matching domains again. Use a monotonic clock for elapsed time.
- Validate and calculate. Reject invalid negative counters and non-positive ranges. Apply one-wrap math, convert units once, and prefer package totals so nested domains are not summed twice.
- Test without hardware. Build fake sysfs trees in
tests/test_rapl.pyfor discovery, unreadable files, changing domains, exact-boundary reads, and wrap cases. - Fail helpfully. If powercap is missing, return an unavailable result with a clear Linux requirement. Permission errors should explain the access issue; do not silently substitute zero energy.
How to use it
Check whether this Linux machine exposes readable counters, then run a target repeatedly. The values below are illustrative, not a measurement from this machine.
python -m dol8.cli doctor python -m dol8.cli run workload.py --runs 5 --json run.json
ENERGY: 412.500 J; baseline removed 18.200 J PACKAGE: 412.500 J [####################] 100.0% POWER: avg 29.000 W, peak 46.200 W CONFIDENCE: 5 runs, mean 412.500 J +- 6.200 J, CoV 1.50%, HIGH
Edge cases & gotchas
- RAPL may be absent in a VM, WSL2, or on a kernel that does not expose powercap; DoL8 requires Linux bare metal with readable counters.
- Some systems restrict counter reads. Apply only a permissions change you understand; broader access to powercap data has security implications.
- Very frequent polling can expose quantization noise and add overhead. Slow polling increases the chance of an unseen wrap. DoL8's timeline poller defaults to 100 ms.
- A range corrects one wrap only. If a workload can consume more than one full counter range between reads, the delta is ambiguous.
- Package, core, and DRAM domains are not necessarily independent; adding nested readings can double-count energy.