Quick Usage
Joular Core has one simple interface: open the sources, read them as often as you need, then close them.
Opendetects the hardware asked for (the CPU, the GPU, or both) and opens what is needed to read it.Readtakes one reading of every source that could be opened.Closecloses what was opened.
Each reading gives, for the CPU and for the GPU, whether the source is available, its value, and its unit: energy in joules consumed since the previous reading, or power in watts. See Reading the Measurements for what each one means.
Using from Ada
with Ada.Text_IO; use Ada.Text_IO;
with Joular_Core; use Joular_Core;
procedure Measure is
Measurements : Reading;
begin
Open; -- Detect and open every supported hardware source
for I in 1 .. 5 loop
delay 1.0;
Measurements := Read;
if Measurements (CPU).Available then
Put_Line ("CPU:" & Long_Float'Image (Measurements (CPU).Value)
& (if Measurements (CPU).Unit = Energy then " J" else " W"));
end if;
end loop;
Close;
end Measure;
With Alire, add the library to your project with alr with joularcore.
A full example program is in example/src/example_joular_core.adb. It reads once per second until stopped with Ctrl+C, which closes the sources cleanly. To build and run it:
gprbuild -P example/example.gpr
./example/example_joular_core
It takes two optional arguments, in any order: on Windows, emi, pawnio or hubblo to say how the RAPL counter is read (rather than trying them in turn), and a number of readings to do before stopping. A summary is printed at the end.
./example/example_joular_core emi 10
Using from C
The C declarations are in include/joularcore.h. Build the relocatable (shared) library (see Compilation), then:
#include <stdio.h>
#include "joularcore.h"
joularcore_reading reading;
joularcore_open(1, 1); /* measure the CPU and the GPU */
joularcore_read(&reading);
if (reading.cpu.available)
printf("CPU: %f %s\n", reading.cpu.value, reading.cpu.unit == 0 ? "J" : "W");
joularcore_close();
A full example program is in example/c/main.c. Like the Ada one, it reads once per second until stopped with Ctrl+C. It comes with a Makefile that builds the shared library and the program:
make -C example/c
Using from Python
From Python, the same interface through ctypes:
import ctypes
class Measurement(ctypes.Structure):
_fields_ = [("value", ctypes.c_double), ("available", ctypes.c_int), ("unit", ctypes.c_int)]
class Reading(ctypes.Structure):
_fields_ = [("cpu", Measurement), ("gpu", Measurement)]
lib = ctypes.CDLL("lib/relocatable/libjoularcore.so")
lib.joularcore_read.argtypes = [ctypes.POINTER(Reading)]
lib.joularcore_version.restype = ctypes.c_char_p
lib.joularcore_open(1, 1) # measure the CPU and the GPU
r = Reading()
lib.joularcore_read(ctypes.byref(r))
if r.cpu.available:
print("CPU:", r.cpu.value, "J" if r.cpu.unit == 0 else "W")
lib.joularcore_close()
The library is libjoularcore.dylib on macOS and libjoularcore.dll on Windows.
A full example program is in example/python/main.py, with a Makefile that builds the shared library.
Other languages (C++, Java, Rust, etc.) use the same C interface. See Integration with Systems and Tools.