I wanted to answer one question: which app on my PC is eating my electricity bill?
Task Manager shows percentages. HWiNFO shows CPU and GPU watts. Nothing mapped the two together and displayed total watts. So I built WattSeal — a per-app, real-time power monitor. The easy part was Linux. Windows nearly finished me.
Linux: embarrassingly simple
On Linux, RAPL (Intel's Running Average Power Limit interface) exposes CPU energy counters as plain files:
/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj
Read it. Wait. Read it again. Subtract. Divide by elapsed time. You have watts. That's it. You need sudo, but the interface is clean, documented, and stable.
AMD works the same way on modern Ryzen. Two reads, one subtraction.
I had a working Linux prototype in a weekend.
Windows: where it gets painful
On Windows there are no files to read. CPU energy counters live in MSRs — Model-Specific Registers — which are hardware registers accessible only from kernel mode. To read them from userspace you need a kernel driver.
We use WinRing0, an open-source driver that exposes MSR access to userspace. Loading it requires admin privileges, and on some systems it triggers antivirus alerts because kernel drivers that read arbitrary hardware registers look suspicious to heuristic scanners. Fun times.
Then the actual register addresses. Intel's are documented:
-
0x606for the power unit -
0x611for package energy
AMD's? 0xC001029B for package, 0xC001029A for cores. These are in AMD's processor programming reference, but the document is dense and the relevant section took an afternoon to find.
Then the unit normalization. The counters store energy as raw integers, not joules. The scale factor — how many joules per integer unit — is stored in a separate register as a power-of-two exponent. Get this wrong and your watt readings are off by a factor of 32. I got it wrong first.
Then counter wraps. The energy registers are 32-bit on most implementations. On a power-hungry machine under full load, they wrap around in minutes. Your polling loop has to detect the wrap and handle it correctly or you get negative power readings and very confused users.
None of this is insurmountable. All of it took longer than expected.
Per-app attribution
Once you have total CPU watts from RAPL, you need to split it across processes. We use CPU usage percentage per process — normalized by core count to match what you'd see in Task Manager — then attribute proportionally against total CPU utilization.
It's an approximation. A process running heavy AVX instructions draws more per CPU% than one in a tight sleep loop. But validated against smart plug measurements across typical workloads — gaming, development, browsing, video calls — the error stays within a range that's useful and honest. You can meaningfully see that Chrome is drawing 8W while your compiler draws 25W.
For GPU, NVML (NVIDIA's management library) exposes both total GPU power and per-process GPU utilization directly. That attribution is cleaner.
The components without sensors
RAM, disk, and network don't have per-process energy sensors we can read directly.
RAM is handled differently: DRAM power is relatively stable and predictable based on your installed configuration — capacity, number of slots, and whether the sticks are running at rated speed. We estimate it from these static characteristics rather than live sensor data.
Disk and network are estimated from actual bytes read/written/transferred, with different coefficients depending on drive type (SSD vs HDD, which we detect at startup) and network interface speed. These are rough but they move meaningfully when you start a large file transfer or backup job.
Overhead: eating your own cooking
A power monitor that itself consumes significant power is self-defeating. WattSeal is split into two processes: a background collector and a UI (built with iced) that you can close independently.
Current numbers in production:
- Collector: ~0.1% CPU, ~7MB RAM
- Tray icon: ~0.7MB RAM
- UI when open: <80MB RAM
- Estimated background power consumption: <0.1W
For comparison, a smart plug — the hardware alternative for measuring system power — draws 1–2W just being plugged in, and can't tell you anything about individual apps. WattSeal costs less to run than the tool it replaces.
Where it ended up
WattSeal is free, open-source (GPLv3), and works on Windows, macOS, and Linux. It converts per-app wattage to electricity cost and CO₂ based on your local grid. All data stays local in SQLite.
Source: github.com/Daminoup88/WattSeal
If you're building anything in the systems/observability space on Windows and need to read hardware registers, the WinRing0 integration pain is real — happy to answer questions about it below.
Top comments (0)