Overview
Joular Energy Meter is a desktop application that monitors, in real time, the power and energy consumption of your computer (CPU and GPU) and of a process or application, on Windows, Linux, macOS and FreeBSD. It also estimates the carbon emissions and the cost of that energy.
Joular Energy Meter is part of the
project.
Like PowerJoular, it does the measuring through two Ada libraries we developed, Joular Core for the energy of the CPU and the GPU, and CPU Load for the CPU usage. The application itself is written in C with LVGL and SDL2, so it looks and works the same on every system.
The official website of Joular Energy Meter is: https://www.noureddine.org/research/joular/energymeter.
Features
- Monitor the power and energy of the CPU, the GPU and the whole machine
- Monitor a process, an application (all its processes), or a command started from the application
- Estimate carbon emissions with the carbon intensity of your country’s electricity (from Ember), of an energy source, or your own value, and the cost of the energy
- Measure the idle power of the machine, to see what a program adds to it
- Read a power meter at the plug, through the CSV file its program writes
- Save the power data to CSV files, in the same format as PowerJoular
- The same application on Linux, Windows, macOS and FreeBSD
License
Joular Energy Meter is licensed under the GNU GPL 3 license only (GPL-3.0-only).
Copyright (c) 2026, Adel Noureddine. All rights reserved. This program and the accompanying materials are made available under the terms of the GNU General Public License v3.0 only (GPL-3.0-only) which accompanies this distribution, and is available at: https://www.gnu.org/licenses/gpl-3.0.en.html
The third-party works shipped with Joular Energy Meter (LVGL, SDL2, the fonts and icons, Ember’s carbon intensity data) are listed with their licences in the README.
Author : Adel Noureddine
Supported Platforms
Joular Energy Meter runs on Linux, Windows, macOS and FreeBSD, and reads:
| OS | CPU | GPU |
|---|---|---|
| Linux | Intel, AMD, Raspberry Pi | Nvidia, AMD |
| Windows | Intel, AMD | Nvidia, AMD |
| macOS | Apple Silicon, Intel | Apple Silicon |
| FreeBSD | Intel, AMD | Nvidia |
The hardware is read by our Joular Core library, the same way as in PowerJoular:
- Intel and AMD processors through RAPL: the powercap files on Linux, the Energy Meter Interface (Windows 11), PawnIO or Hubblo’s driver on Windows, and the
cpuctldriver on FreeBSD. - Macs through
powermetrics, installed with macOS. Apple Silicon gives the CPU and the GPU of the chip, Intel Macs the CPU only. - Raspberry Pi through our regression power models.
- Nvidia cards through NVML (installed with the driver), and AMD cards through the amdgpu hwmon files on Linux and ADLX on Windows.
The CPU usage of the machine, of a process and of an application is read by our CPU Load library.
Whole machine means the processor and the graphics card only. The screen, memory, disks and the losses of the power supply are not measured, so the computer draws more at the plug. A power meter at the plug can be added for that (see Idle Power and Plug Meter).
Required privileges
The CPU load is always read, but the CPU power needs some rights on most systems. When they are missing, a notice says what to do: on Linux, macOS and Windows, with a button that asks the system for the administrator (through the system’s own dialog, never a password field of ours), and on Linux, macOS and FreeBSD, with a button to copy the command instead.
- Linux: the RAPL files are readable by root only (CVE-2020-8694). Allow reading power asks for the administrator through polkit (
pkexec), and makes the processor’s counters readable by every user of the machine until the next boot. The application itself keeps running as you. The same by hand, after each boot:sudo chmod -R a+r /sys/class/powercap/intel-rapl. Or start the application withsudo, under X11 (not Wayland). - Windows: nothing to do on Windows 11. On older versions, install the PawnIO driver, then Restart as administrator (UAC asks), or install Hubblo’s RAPL driver, which needs no administrator.
- macOS:
powermetricsneeds root. Restart with admin rights asks for your password in macOS’s dialog, then starts the application again as root, with your files and settings still yours. Or from Terminal:sudo "/Applications/Joular Energy Meter.app/Contents/MacOS/joularenergymeter". - FreeBSD: load the cpuctl driver (
sudo kldload cpuctl, orcpuctl_load="YES"in/boot/loader.conf), and start the application withsudounder X11. Thekmemgroup also works, but it can read all memory through/dev/mem. - Nvidia and AMD graphics cards, and Raspberry Pi, need nothing.
On Windows and macOS, following a process of another user also needs the administrator.
Installation
Ready-made packages are released in our GitHub repository release page and in the build workflow. They need no compiler, Alire or MSYS2.
Every package has the program, the carbon intensities of the countries, the README and the licences.
Linux
For x86_64 and aarch64:
Debian, Ubuntu:
sudo apt install ./joularenergymeter_<version>-1_amd64.deb
Fedora:
sudo dnf install ./joularenergymeter-<version>-1.x86_64.rpm
Arch Linux:
sudo pacman -U joularenergymeter-<version>-1-x86_64.pkg.tar.zst
These packages also install SDL2.
The AppImage has SDL2 inside and runs on any distribution: make it executable with chmod +x, then start it.
The tar.gz needs the SDL2 package (libsdl2-2.0-0 on Debian and Ubuntu, SDL2 on Fedora).
All of them need glibc 2.35 or newer (Debian 12, Ubuntu 22.04, Fedora 36 and later), as they are built on Ubuntu 22.04. On Raspberry Pi, this means a 64 bits OS.
macOS
Open the .dmg and drag the application to Applications.
It is one application for Apple Silicon and Intel Macs, with SDL2 inside, and needs macOS 15 or newer (GNAT’s Ada runtime is built for 15).
The application is only signed ad hoc, so macOS blocks it the first time: open System Settings > Privacy & Security and click Open Anyway.
Started from Finder, it writes its CSV files to the home folder. To read the power, it needs root (see Required privileges).
Windows
Run the .msi (it installs to Program Files, adds a Start menu shortcut, and is removed from Settings > Apps), or unzip the .zip and run joularenergymeter.exe.
Both ship SDL’s own SDL2.dll.
The installer is not signed, so SmartScreen asks once (More info, then Run anyway).
FreeBSD
sudo pkg install sdl2
sudo pkg add joularenergymeter-<version>-freebsd14-amd64.pkg
pkg add looks for dependencies only beside the file, hence SDL2 first.
A tar.gz is also available.
The package is made for the FreeBSD version it was built on.
From the source code
Quick Usage
Start Joular Energy Meter, with the rights it needs to read the power (see Required privileges).
The window has two tabs:
- Setup: what to measure (the whole machine, a process by its ID, an application by its name, or a command to start), how often (every 1 to 10 seconds), for how long, and whether to record to a CSV file. Optionally, the electricity used for the carbon emissions and the cost, the idle power, and a plug meter.
- Readings: the power now, and the energy and carbon emissions since the start, of the followed program and of the whole machine, the share of the processor and the graphics card, and a chart of the last 120 measurements.
Press Start (or Enter in a field) to start measuring. The bar at the bottom says what is measured, for how long, and the last message.
While measuring, the interval, the length and the electricity can still be changed (a new interval restarts the chart). Pause stops the clock and the energy count until you resume, and the length only counts the measured time. After Stop, the power shown is the average of the session.
Copy summary puts the session in plain text on the clipboard, for a report or an email: what was measured, when and for how long, the average power, the energy, the carbon emissions, and the price per kWh (with the cost of the followed program, when there is one).
Resting the pointer on the name of a figure shows what it means.
To see what a program adds to an idle machine, measure the idle power first (see Idle Power and Plug Meter).
Compilation and Packages
Joular Energy Meter is written in C, and is linked with the Joular Core and CPU Load libraries, written in Ada. It needs GNAT and GPRBuild, SDL2 (2.0.18 or newer), and LVGL 9.6.
LVGL goes in the lvgl folder, at the commit of its release/v9.6 branch that the CI builds against (see .github/workflows/build.yml):
git clone https://github.com/joular/joular-energy-meter
cd joular-energy-meter
git init lvgl && git -C lvgl fetch --depth 1 https://github.com/lvgl/lvgl.git 8df3de9c4c5e45ad7b0fef5adc2fa6eaa5d21579 && git -C lvgl checkout FETCH_HEAD
The program is created as bin/joularenergymeter.
SDL2
macOS:
brew install sdl2
Debian, Ubuntu:
sudo apt install libsdl2-dev
Fedora:
sudo dnf install SDL2-devel
Windows, in Alire's msys2 shell:
pacman -S mingw-w64-x86_64-SDL2
FreeBSD:
sudo pkg install sdl2
Compilation with Alire
Alire downloads GNAT, GPRBuild and the two libraries, and checks that SDL2 is installed (and offers to install it):
alr build
When SDL2 is somewhere else:
alr build -- -XSDL2_CFLAGS="-I<folder>" -XSDL2_LIBS="-L<folder> -lSDL2"
On macOS, use alr build -- -XDev=True for a program run from the source folder.
Homebrew’s SDL2 loads SDL3 by name, and this switch tells dyld where to find it.
The packaged application is built without it, so it looks for nothing outside the application when run with sudo.
Compilation with GNAT and GPRBuild
Check out the two libraries next to the Joular Energy Meter folder, then point GPRBuild at them:
cd ..
git clone --depth 1 --branch 0.1.0 https://github.com/joular/cpuload.git
git clone --depth 1 --branch 0.1.0 https://github.com/joular/joularcore.git
cd joular-energy-meter
gprbuild -P joularenergymeter.gpr -aP../joularcore -aP../cpuload -p
The OS is detected from the compiler, and can be forced with -XPJ_OS=linux, windows, macos or freebsd.
GPRBuild does not look where Homebrew puts SDL2, so on macOS add:
-XSDL2_CFLAGS="-I$(brew --prefix)/include" -XSDL2_LIBS="-L$(brew --prefix)/lib -lSDL2"
On FreeBSD, this is the only way to build, as Alire has no FreeBSD SDL2 package.
Use GNAT 15 or newer (sudo pkg install gprbuild gnat15, then put /usr/local/gnat15/bin first in PATH), as GNAT 12 cannot compile Joular Core’s FreeBSD code.
Packages and installers
The packaging/ folder has one script per system.
Each script builds the program, checks it, and makes the packages in dist/.
The CI runs the same scripts and keeps the packages as artifacts.
The top of each script lists what it needs.
| System | Run | Makes |
|---|---|---|
| Linux | packaging/linux.sh | .tar.gz, .deb, .rpm, Arch Linux .pkg.tar.zst, .AppImage |
| macOS | packaging/macos.sh | .zip with Joular Energy Meter.app, .dmg |
| Windows | powershell -ExecutionPolicy Bypass -File packaging\windows.ps1 | .zip, .msi |
| FreeBSD | packaging/freebsd.sh | .tar.gz, .pkg |
The Linux packages need the glibc of the build machine or newer, so build them on an old distribution (the CI uses Ubuntu 22.04).
On macOS, the script builds the application’s binary in bin/app, so bin/joularenergymeter stays the one that runs from the source folder, and two binaries (arm64 and x86_64) make one universal application.
A binary built by hand needs SDL2 from where it was built (Homebrew, MSYS2), so ship the packages instead.
Measuring a Program
Joular Energy Meter follows one program at a time, besides the whole machine:
- Process: one process, by its ID.
- Application: every process whose program has that name (
firefox, not Firefox.app). On macOS, all the programs inside the application bundle count too. On Windows, a trailing.exeis ignored. - Command: a command started by Joular Energy Meter at Start, and measured from its first instant.
The power of a program
The power of the followed program is its share of the processor’s power only, as in PowerJoular:
program power = CPU power × program CPU usage / machine CPU usage
The graphics card is not shared out to programs.
Share of CPU is the fraction of the machine’s processing capacity the program used (all of one core out of eight is 12.5 %), not of the processor’s power. The share of the machine shown next to the program’s name is its power divided by the power of the CPU and the GPU.
So on a quiet machine, a program gets most of the processor’s idle power too. Above idle takes it out (see Idle Power and Plug Meter).
A program that cannot be read
A process that has ended, or that the system does not let us read, shows a dash instead of 0 %, and is written as -1 in the CSV files, as PowerJoular does.
A process that ended stays ended: a new process given the same ID later is not followed.
Commands
On Linux, macOS and FreeBSD, the command runs through /bin/sh, so python3 bench.py > out.txt works, and the program itself is followed, not the shell.
On Windows, it is a program and its arguments, without the shell’s > or &&.
The command starts in the current folder.
Started with sudo, Joular Energy Meter runs the command as you, not as root.
Started as administrator on Windows, it cannot run commands.
Only the command’s own process counts as the program: the processes it starts (the compilers of make, for example) are in the machine’s reading, not in the program’s.
When the command ends, its exit status is shown, and the measuring stops if the length is Until it ends. Stop leaves the command running.
Idle Power and Plug Meter
Both are optional, and set in the Setup tab.
Idle power
The idle power is what the machine draws doing nothing, in watts. It can be typed, or measured with Measure…: a window of its own measures the whole machine for 30 seconds while you leave it alone, without recording and without touching the readings, then offers its average. On macOS and Windows, the machine does not go to sleep while it measures.
A typed value is split between the processor and the graphics card as the last measured one was (all to the processor without one). The value is kept for the next launches, and an empty field means no idle power.
With an idle power, the chart of the machine shows a dashed idle line, and the Above idle switch shows the readings without it: what the program, or anything you run, adds to an idle machine.
- For the machine, the processor and the graphics card: the power minus their idle power.
- For the program: its share of the processor’s power above the processor’s idle power.
- Energies: the energy minus the idle power times the measured time (for the program, times its share of the processor over that time), so the ups and downs around the idle power even out.
A figure below zero shows as 0.
The idle power is only as good as the 30 seconds it was measured in: measure it again after a change (power settings, a dock, other programs started at login).
Plug meter
Whole machine is the processor and the graphics card only. A power meter between the plug and the socket measures the whole computer, screen and power supply included.
Choose… picks the CSV file the meter’s program writes as it measures, such as PowerSpyCli for PowerSpy 2 meters. From the next Start, the readings get an At the plug row and the chart an At the plug choice. Remove stops using it.
The rows of the file are time;watts, time,watts or separated by a tab, and a header is skipped.
When the meter’s program starts the file again, it is read again from the top.
Only the rows written after Start count: each measurement takes the average of the rows written during it, or the last one for up to 5 seconds.
After that, a warning shows, and the plug has no reading until a new row comes.
The plug’s readings are not written to the recording CSV files.
Carbon Emissions and Cost
The energy since the start is turned into grams of CO2 equivalent, for the machine and for the followed program:
carbon (g CO2e) = energy (kWh) × carbon intensity (g CO2e per kWh)
The carbon intensity is chosen in the Setup tab, under Electricity:
- Country: the yearly average of the country’s electricity, from Ember’s yearly electricity data, over the life cycle of the power plants. The first time, the country of the time zone is chosen (on Windows, the one of the region setting), or the world’s average. After that, the one chosen last time.
- Country, this month: the average of the current calendar month, from the latest year Ember’s monthly electricity data has it, as electricity is cleaner in some seasons. Ember has monthly figures for fewer countries (88 and the world). Elsewhere, the yearly average is used, and the note under it says so.
- Energy source: electricity from a single source, such as your own solar panels.
- Own value: your own figure in g CO2e per kWh, such as your supplier’s.
The energy sources use the life-cycle medians of the IPCC (AR5, WG3, Annex III), which Ember uses too, in g CO2e per kWh:
| Source | Wind | Nuclear | Hydro | Geothermal | Solar | Bioenergy | Gas | Oil | Coal |
|---|---|---|---|---|---|---|---|---|---|
| g CO2e per kWh | 11 | 12 | 24 | 38 | 48 | 230 | 490 | 700 | 820 |
Oil is Ember’s figure for oil and other fossil fuels.
Changing the carbon intensity works out the emissions again from the last measurement, including after Stop. The emissions are not written to the CSV files, which keep PowerJoular’s columns.
Cost
With a price per kWh (a comma or a point for the decimals) and a currency, the cost of the machine’s energy since the start is shown, with the followed program’s part of it. The currency is written as text (EUR, $, £, CHF…), as the font has no euro sign. An empty price means no cost.
Everyday equivalents
Under the cost, the machine’s energy and emissions are given in everyday terms, from the US EPA’s greenhouse gas equivalencies:
- A smartphone charge takes 0.019 kWh.
- An average gasoline car emits 3.93 × 10-4 t CO2e per mile, so 244 g per km.
- Below one phone charge, the energy is given as the time a 10 W LED bulb would take.
These are orders of magnitude for people, not results to report.
The data files
The values of the countries are read from carbon-intensity.csv and carbon-intensity-monthly.csv, beside the program (in Contents/Resources of the application on macOS), or in ../share/joularenergymeter/ from it, as the Linux and FreeBSD packages install them.
Without these files, the same values built into the program are used.
An edited file works without compiling again:
carbon-intensity.csv: one row per country,ISO 3 code,Area,Year,grams per kWh. The world has an empty code.carbon-intensity-monthly.csv: one row per country and month,ISO 3 code,Year,Month,grams per kWh. A country needs all twelve months, or it has none.
To update them, run from the source folder:
python3 data/update.py
It downloads Ember’s latest yearly and monthly data, and rewrites both files and their built-in copy, src/carbon_data.c.
python3 data/update.py YEARLY.csv MONTHLY.csv uses files already downloaded.
Ember adds a new year once a year, and new months each month.
CSV Files
With Record to a CSV file on, Joular Energy Meter writes a row at every measurement, in the same format as PowerJoular, so the same scripts read both.
The file is added to, not emptied, and a new or empty file starts with a header:
Timestamp,CPU Usage,Total Power,CPU Power,GPU Power
1756681930,0.2460,18.4500,15.2000,3.2500
The timestamp is in whole Unix seconds, the CPU usage goes from 0.0 to 1.0, the power is in watts, with four digits after the dot. Each row is written to the disk at once, so the file can be read while measuring, and its rows survive a crash.
When following a process, an application or a command, a second file is written next to the first, named after the process ID or the program’s name (power-144.csv or power-firefox.csv for power.csv).
For a command, the name is its program’s, without its folder.
The characters a file name cannot hold are replaced by _.
It has the CPU usage and the power of the followed program:
Timestamp,CPU Usage,CPU Power
1756681930,0.0310,1.9154
Both value columns hold -1.0000 when the program could not be read at all: it has ended, or the system does not let us read it.
That is not the same as 0.0000, a program that was read and used no CPU time.
An application with no running process is written as 0.0000, as in PowerJoular.
The carbon emissions, the cost, the idle power and the plug meter are not written to the CSV files, which keep PowerJoular’s columns.
Writing files safely
On Linux, macOS and FreeBSD, the CSV files are only written to plain files: a symbolic link, a hard link, or anything else that is not a plain file is refused, and the reason is shown.
A file created while running with sudo belongs to you, not to root.
A file that cannot be written is reported once, and the measuring goes on.
Options and Settings
Command line options
Everything is chosen in the window, and the command line has only these options:
| Option | What it does |
|---|---|
--start | Start measuring at once, with the choices kept from the last time |
--idle | Open the window that measures the idle power |
-v, --version | Print the versions of Joular Energy Meter, Joular Core and CPU Load, and stop |
-h, --help | Print the help, and stop |
Settings file
The choices are kept for the next launch: what to measure (except a process ID), the interval, the length, the recording and its file, the electricity, the price, the idle power, the plug meter, the look and the zoom.
They are saved at each Start and on quit, as key=value lines, in:
| OS | File |
|---|---|
| Linux, FreeBSD | ~/.config/joularenergymeter/settings (or in $XDG_CONFIG_HOME when set) |
| macOS | ~/Library/Application Support/Joular Energy Meter/settings |
| Windows | %APPDATA%\Joular Energy Meter\settings |
Under sudo, they go to your own folder, not root’s.
Delete the file to go back to the defaults.
Look and zoom
The sun or moon key at the top right picks a light or a dark look, or one like the system’s (the default): the appearance of macOS and Windows, and GNOME’s style on Linux.
On Linux and FreeBSD under sudo, “like the system” is light.
Ctrl + and Ctrl - (Cmd on macOS) zoom the window from 80 to 150 %, and Ctrl 0 goes back to 100 %. The window grows with the zoom, so a zoom larger than the screen can hold is refused.
Keyboard and accessibility
Every control works from the keyboard: Tab moves between them, Space or Enter uses one, and the arrows choose in a list. In the file browser, the arrows move, Enter opens, Backspace goes up, letters jump to a name, and Esc cancels.
The help shown on hover needs a mouse. Screen readers cannot read the window, as LVGL draws it itself, but Copy summary gives the figures as text.
Sleep
While measuring, macOS and Windows do not go to sleep on idle (the screen still can, and closing the lid still does).
On Linux, use systemd-inhibit --what=sleep for long runs.
How Joular Energy Meter Works
Joular Energy Meter is written in C, with LVGL drawing the window on top of SDL2, so it has the same interface on every system. The hardware is measured by our Joular Core library, and the CPU usage by our CPU Load library. Both are written in Ada, and are linked into the program as static libraries with their Ada runtime, so it is one binary.
The measuring thread
The libraries are only called from a measuring thread, so a slow reading (powermetrics on macOS, for example) never blocks the window.
The thread queues its measurements for the window, up to four minutes of them at 1 second while the window is blocked (a window dragged on Windows, a menu held open on macOS).
Beyond that, the oldest are dropped, and counted as missed.
An idle window costs nothing: the program sleeps until the next event or the next measurement.
A measurement
Each cycle, Joular Energy Meter:
- Reads the CPU time of the whole machine, of the followed program, and of Joular Energy Meter itself, from the same sample.
- Reads the processor and the graphics card from Joular Core.
- Divides the energy given by the hardware (RAPL, for example) by how long the cycle actually took, so the watts are right even when a cycle takes longer than the interval, and when the interval is changed while measuring. Hardware that gives watts (
powermetrics, NVML) is used as it is. - Shares the processor’s power out to the followed program (see Measuring a Program).
- Adds the power times the length of the cycle to the energy since the start.
A cycle during which the machine slept for more than 2 seconds is dropped, and counted as missed.
From the energy since the start:
- The average power is the energy divided by the measured time.
- The spread is the standard deviation of the power around this average, each measurement weighted by the time it covers.
- A year at this average is the average power for 365.25 days, day and night.
The share of the CPU used by Joular Energy Meter itself is shown under the chart (on macOS, without the powermetrics it starts).
Asking for the administrator
When the power cannot be read for lack of rights, Joular Energy Meter asks through the system’s own dialog, never through a password field of its own:
- Linux:
pkexec chmod a+ron the energy counter of each top-level RAPL zone (intel-rapl:N/energy_uj), which stays readable by every user until the next boot. The application itself keeps running as you. - macOS: the administrator dialog (
osascriptwith administrator privileges) starts the application again as root, aspowermetricsneeds. - Windows: UAC starts the application again as administrator, for the PawnIO driver.
Restarting saves the settings first, so the new run starts where the old one was.
Running as root
Started with sudo, Joular Energy Meter keeps your files yours:
- CSV files it creates belong to you (see CSV Files).
- Settings go to your own folder, not root’s (see Options and Settings).
- Copy summary goes to your own clipboard on macOS, not root’s.
- Commands it starts run as you.
On Linux, a program run as root cannot open a window on Wayland, so use X11, or Allow reading power instead of sudo.