Profiling modes#
The quickstart covers the shortest path from a few regions to a profile. This page collects the options for choosing how much code to measure and how much data to retain. Start with explicit regions; enable broader modes only when the extra detail answers a specific question.
Explicit regions#
The default CLI mode activates regions already present in the application:
scope-profiler run app.py -o profile.h5
Use tags to select a subset of regions. A repeated --tag uses OR
semantics:
import scope_profiler as sp
with sp.region("linear_solve", tags=["solver", "expensive"]):
solve()
scope-profiler run --tag solver --tag io app.py
Recursive tracing#
For code without explicit regions, or when function-level attribution is needed, opt in to recursive tracing:
scope-profiler run --recursive app.py
--include and --exclude accept shell-style globs for recursively
traced function names. --all additionally includes installed packages
and the standard library:
scope-profiler run --recursive \
--include 'my_app.solver.*' \
--exclude '*logging*' \
app.py
Use --entrypoint main to name the traced application entrypoint.
Recursive tracing has more overhead than explicit regions, so filters
are recommended for large applications.
Python lifecycle shortcuts#
The CLI is equivalent to a managed Python session. For a callable
entrypoint, use sp.run():
import scope_profiler as sp
sp.run(main, output="profile.h5")
Use the session decorator when the application should own its entrypoint:
@sp.session(file_path="profile.h5")
def main():
run_application()
For a script that cannot use a context manager, opt in to a guarded exit hook:
sp.setup(file_path="profile.h5", auto_finalize=True)
Output and summaries#
The output extension selects the format. --no-output is useful for
checking regions or printing a summary without leaving a file behind:
scope-profiler run -o profile.h5 app.py
scope-profiler run -o profile.json app.py
scope-profiler run -o report.html app.py
scope-profiler run --no-output app.py
Use --label to identify a run in comparisons:
scope-profiler run --label baseline app.py
Concurrency#
Thread and asynchronous task tracking are opt-in Python API modes:
with sp.session(track_threads=True):
run_parallel_work()
with sp.session(track_async=True):
asyncio.run(main())
track_async=True also tracks task suspension time, so a region held
across an await can be separated into running and awaiting time.
Reducing trace volume#
Aggregation mode stores counts and timing totals without per-call events:
scope-profiler run --aggregation-mode app.py
For periodic workloads, pause profiling between phases or use
sample_every():
import scope_profiler as sp
from scope_profiler import ProfileManager
with sp.session(file_path="profile.h5"):
with ProfileManager.sample_every(10) as profile_step:
for step in range(steps):
with profile_step(step):
simulation.step()
See Configuration for line profiling, GPU timing, NVTX, MPI, LIKWID, memory profiling, and HDF5 tuning options.
Notebook workflows#
Load the IPython magics when profiling from a notebook:
%load_ext scope_profiler.ipython_magics
Use %%scope for a measured cell, %%scope_recursive when nothing is
instrumented, %%scope_line for line timings, and %%scope_agg for
very hot regions. %scope_compare, %scope_load, and %scope_export
support the follow-up analysis workflow. See Jupyter/IPython magics for
the complete reference.