Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quick Start

Getting started with Joule Profiler is easy and straightforward.

First, install the latest version:

curl -fsSL https://raw.githubusercontent.com/jwoirhaye/joule-profiler/main/install.sh | bash

Basic Measurement

The simplest way to measure energy consumption is to run your program with the profiler:

joule-profiler profile -- ./my-program arg1 arg2

This will execute your program and display energy consumption metrics in the terminal once it completes:

╔════════════════════════════════════════════════╗
║  Command                                       ║
╚════════════════════════════════════════════════╝
  python3 main.py
 ────────────────────────────────────────────────
  Duration            :       3013 ms
  Exit code           :          0

╔════════════════════════════════════════════════╗
║  Phase: START -> END                           ║
╚════════════════════════════════════════════════╝
  Duration            :       3013 ms
  Start token         :      START
  End token           :        END

┌────────────────────────────────────────────────┐
│ RAPL (perf_event)                              │
└────────────────────────────────────────────────┘
  CORE-0              :    7299194 µJ
  PACKAGE-0           :   15104492 µJ
  PSYS                :   35101074 µJ
  UNCORE-0            :     355224 µJ

Phases

Put some prints separating your program’s parts:

...

print("__SETUP_PHASE__", flush=True)

setup()

print("__WORKLOAD_PHASE__", flush=True)

workload()

print("__CLEANUP_PHASE__", flush=True)

cleanup()

...

Don’t forget to flush the standard output after each print, see troubleshooting.

Now, lauch Joule Profiler:

joule-profiler profile -- ./my-program arg1 arg2

You will get something like:

__SETUP__
__WORKLOAD__
__CLEANUP__
╔════════════════════════════════════════════════╗
║  Command                                       ║
╚════════════════════════════════════════════════╝
  python3 main.py
 ────────────────────────────────────────────────
  Duration            :       3013 ms
  Exit code           :          0

╔════════════════════════════════════════════════╗
║  Phase: START -> __SETUP__                     ║
╚════════════════════════════════════════════════╝
  Duration            :         10 ms
  Start token         :      START
  End token           : __SETUP__ (line 0)

┌────────────────────────────────────────────────┐
│ RAPL (perf_event)                              │
└────────────────────────────────────────────────┘
  CORE-0              :     184997 µJ
  PACKAGE-0           :     226806 µJ
  PSYS                :     387084 µJ
  UNCORE-0            :       4150 µJ

╔════════════════════════════════════════════════╗
║  Phase: __SETUP__ -> __WORKLOAD__              ║
╚════════════════════════════════════════════════╝
  Duration            :       1000 ms
  Start token         : __SETUP__ (line 0)
  End token           : __WORKLOAD__ (line 1)

┌────────────────────────────────────────────────┐
│ RAPL (perf_event)                              │
└────────────────────────────────────────────────┘
  CORE-0              :    1856750 µJ
  PACKAGE-0           :    3949645 µJ
  PSYS                :    8571228 µJ
  UNCORE-0            :      85571 µJ

╔════════════════════════════════════════════════╗
║  Phase: __WORKLOAD__ -> __CLEANUP__            ║
╚════════════════════════════════════════════════╝
  Duration            :       1000 ms
  Start token         : __WORKLOAD__ (line 1)
  End token           : __CLEANUP__ (line 2)

┌────────────────────────────────────────────────┐
│ RAPL (perf_event)                              │
└────────────────────────────────────────────────┘
  CORE-0              :    1398742 µJ
  PACKAGE-0           :    3311218 µJ
  PSYS                :    7377380 µJ
  UNCORE-0            :      58105 µJ

╔════════════════════════════════════════════════╗
║  Phase: __CLEANUP__ -> END                     ║
╚════════════════════════════════════════════════╝
  Duration            :       1003 ms
  Start token         : __CLEANUP__ (line 2)
  End token           :        END

┌────────────────────────────────────────────────┐
│ RAPL (perf_event)                              │
└────────────────────────────────────────────────┘
  CORE-0              :    1468383 µJ
  PACKAGE-0           :    3395080 µJ
  PSYS                :    7314697 µJ
  UNCORE-0            :     137817 µJ

Custom Output Format

By default, the output is shown in the terminal with a human-readable format. For further analysis or integration with other tools, you can export results in different formats:

# Export results as JSON for programmatic analysis
joule-profiler --json profile -- ./my-program

# Export results as CSV for spreadsheet analysis
joule-profiler --csv profile -- ./my-program

An output file will be generated at the end of the profiling. These formats make it easy to process results with scripts or import them into visualization tools.

Additional Options

Specify an Output File

You can choose where to export your results:

# Save results to a file (format determined by extension or --json/--csv flags)
joule-profiler -o results.json --json profile -- ./my-program

This is particularly useful when running multiple benchmarks.

GPU Profiling

If your system has an Nvidia GPU and you want to measure GPU energy consumption alongside CPU:

# Include GPU metrics in the measurement
joule-profiler --gpu profile -- ./my-program

Performance Counters

Joule Profiler supports perf_event performance counters on Linux systems, you can activate this feature with the --perf flag.

joule-profiler --perf profile -- ./my-program

GPU profiling requires the NVML library (part of NVIDIA driver installation).

Choosing RAPL Backend

By default, Joule Profiler measures RAPL counters using either perf_event (default) or Powercap backend depending on your system.

You can explicitly choose which backend to use:

# Use Powercap backend (requires root)
sudo joule-profiler --rapl-backend=powercap profile -- ./my-program

# Use perf_event backend (lower overhead, may require kernel configuration)
joule-profiler --rapl-backend=perf profile -- ./my-program

The choice of backend can affect measurement granularity and permission requirements. See the RAPL documentation for details on each backend.


For more advanced usage including phase-based profiling, iterations, and custom metric sources, see the examples folder.