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

Phases

Overview

Phase-based profiling is the key feature that distinguishes Joule Profiler from other energy profilers. It enables energy measurement of specific sections of your program, allowing you to identify which parts contribute most to energy consumption.

Why Use Phases?

Identify Energy Hotspots

Instead of measuring total program energy, phases let you pinpoint expensive sections:

print("__INIT__", flush=True)
loading()

print("__WORK__", flush=True)
process()

print("__CLEANUP__", flush=True)

Each phase appears separately in the results, showing its individual energy consumption.

Exclude Initialization

Interpreted languages (Python, JavaScript, Ruby) have significant startup overhead that dominates short programs:

# Python interpreter initialization can be 50-100ms
# Your actual work might be only 10ms
sudo joule-profiler profile -- python my_script.py
# Result: 90% of energy is interpreter startup, not what you want to measure

If you want to exclude this initialization phase, then using phases might be a good answer:

# my_script.py
import heavy_libraries
model = load()  # Initialization overhead

print("__START__", flush=True)  # Mark the beginning of actual work
process()    # This is what you want to measure
print("__END__", flush=True)
sudo joule-profiler profile --token-pattern "__START__|__END__" -- python my_script.py

Now you measure the __START__ to __END__ phase, excluding interpreter startup and library loading.

Implementation Notes

Phases are detected by monitoring the program’s stdout for tokens matching a regular expression. The profiler spawns the program and capture the standard output. Then, it scans each line and triggers measurements when tokens matching the configured regex pattern are detected. Finally, it associates metrics to each phase.

Future versions may support lower-overhead mechanisms like inter-process communication with language-specific wrappers to minimize the overhead introduced by I/O operations.