Quickstart#
This page walks through the core workflow: session, instrument, and inspect. A session sets up profiling and finalizes it automatically, even when the profiled code raises an exception.
1. Start a session#
Use ProfileManager.session() as the default entry point. Configuration
arguments are passed directly to the session:
from scope_profiler import ProfileManager
with ProfileManager.session():
# Profile regions inside this block.
run_application()
All regions created inside the session — even in other modules — share its configuration.
2. Instrument your code#
Decorator#
Use @ProfileManager.profile to wrap an entire function:
@ProfileManager.profile("matrix_multiply")
def matrix_multiply(a, b):
return a @ b
The decorator also works without an explicit name — it uses the function name by default:
@ProfileManager.profile
def matrix_multiply(a, b):
return a @ b
To include nested Python calls made by a decorated function:
with ProfileManager.session(recursive_profile=True):
@ProfileManager.profile("solver_step")
def solver_step():
return advance_state() # nested calls are recorded automatically
Context manager#
Use ProfileManager.profile_region() for finer-grained control:
for step in range(num_steps):
with ProfileManager.profile_region("time_step"):
evolve(state, dt)
with ProfileManager.profile_region("io"):
write_checkpoint(state)
The two styles can be mixed freely.
3. Finish the session#
When the with block exits, the session writes all buffered data,
merges per-rank HDF5 files, and prints a summary. Use
return_results=True to keep the finalized results in memory:
with ProfileManager.session(return_results=True) as run:
run_application()
results = run.results
Output:
╭────────────────────────┬──────┬─────────────┬─────────────┬───────────╮
│ region │ n │ % session │ total [s] │ avg [s] │
├────────────────────────┼──────┼─────────────┼─────────────┼───────────┤
│ scope_profiler.session │ 1 │ 100.00% │ 2.8e-03 │ 2.8e-03 │
│ └─ matrix_multiply │ 100 │ 5.23% │ 1.4e-04 │ 1.4e-06 │
│ └─ time_step │ 1k │ 52.29% │ 1.4e-03 │ 1.4e-06 │
│ TOTAL │ 1.1k │ 100.00% │ 4.3e-03 │ │
╰────────────────────────┴──────┴─────────────┴─────────────┴───────────╯
╭─ Info ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Summary: profiling_data.h5 (1 rank(s)) │
│ │
│ Explore: │
│ Inspect: scope-profiler inspect ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ TUI: scope-profiler tui ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ │
│ Visualize and export: │
│ Plot: scope-profiler plot default ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o plots --show │
│ Report: scope-profiler report ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o report.html │
│ Export: scope-profiler export plot-data ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o data │
│ Lines: scope-profiler line-profile ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ │
│ Compare runs: │
│ Diff: scope-profiler diff BASE.h5 CANDIDATE.h5 │
│ Check: scope-profiler check BASE.h5 CANDIDATE.h5 │
│ │
│ Durations are in seconds. │
│ Regions may nest, so the summed total can exceed the wall-clock time. │
│ % session uses wall-clock coverage; overlapping recursive calls count once. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
The same table is available from ProfilingResults.print_summary() and
from scope-profiler inspect; pass verbose=False to finalize() to
suppress it.
4. Inspect the data#
After finalization the timing data is saved to profiling_data.h5
(default). Use the built-in CLI to generate a Gantt chart:
scope-profiler plot default profiling_data.h5 --show
See Plotting with the CLI for the other charts and exports it can produce. Or load the data programmatically:
from scope_profiler import read_h5
results = read_h5("profiling_data.h5")
# The quickest look: a summary table of every region.
results.print_summary()
# Or region by region (durations are in seconds).
for region in results:
print(f"{region.name}: {region.num_calls} calls, "
f"avg {region.average_duration:.4f} s")
Complete example#
from scope_profiler import ProfileManager
with ProfileManager.session():
@ProfileManager.profile("main")
def main():
x = 0
for i in range(10):
with ProfileManager.profile_region("iteration"):
x += 1
main()
python example.py
╭────────────────────────┬─────┬─────────────┬─────────────┬───────────╮
│ region │ n │ % session │ total [s] │ avg [s] │
├────────────────────────┼─────┼─────────────┼─────────────┼───────────┤
│ scope_profiler.session │ 1 │ 100.00% │ 5.2e-05 │ 5.2e-05 │
│ └─ main │ 1 │ 67.21% │ 3.5e-05 │ 3.5e-05 │
│ │ └─ iteration │ 10 │ 28.08% │ 1.5e-05 │ 1.5e-06 │
│ TOTAL │ 12 │ 100.00% │ 1.0e-04 │ │
╰────────────────────────┴─────┴─────────────┴─────────────┴───────────╯
╭─ Info ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Summary: profiling_data.h5 (1 rank(s)) │
│ │
│ Explore: │
│ Inspect: scope-profiler inspect ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ TUI: scope-profiler tui ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ │
│ Visualize and export: │
│ Plot: scope-profiler plot default ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o plots --show │
│ Report: scope-profiler report ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o report.html │
│ Export: scope-profiler export plot-data ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 -o data │
│ Lines: scope-profiler line-profile ../../../../../../tmp/scope-profiler-docs-output-0chpptlq/profiling_data.h5 │
│ │
│ Compare runs: │
│ Diff: scope-profiler diff BASE.h5 CANDIDATE.h5 │
│ Check: scope-profiler check BASE.h5 CANDIDATE.h5 │
│ │
│ Durations are in seconds. │
│ Regions may nest, so the summed total can exceed the wall-clock time. │
│ % session uses wall-clock coverage; overlapping recursive calls count once. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯