Profiling modes
Install for this page:
pip install scope-profiler(base install only).
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.
Show code
%%writefile app.pyimport time
import scope_profiler as sp
def solve(): with sp.region("linear_solve", tags=["solver", "expensive"]): time.sleep(0.002)
def write_output(): with sp.region("write_output", tags=["io"]): time.sleep(0.001)
def setup_mesh(): with sp.region("setup_mesh"): time.sleep(0.001)
def main(): setup_mesh() for _ in range(3): solve() write_output()
if __name__ == "__main__": main()Writing app.pyThe cells below profile this small app.py, written into a scratch directory
as the working directory. The command-line cells pass -q to suppress the
per-region summary, and the Python cells pass verbose=False.
Explicit regions
Section titled “Explicit regions”The default CLI mode activates regions already present in the application:
%%bashscope-profiler run -q -o profile.h5 app.pyregion_names("profile.h5")['linear_solve', 'setup_mesh', 'write_output']Use tags to select a subset of regions. A repeated --tag uses OR semantics:
def solve(): time.sleep(0.002)
with sp.session(output=None, verbose=False): with sp.region("linear_solve", tags=["solver", "expensive"]): solve()%%bashscope-profiler run -q -o tagged.h5 --tag solver --tag io app.pyregion_names("tagged.h5")['linear_solve', 'write_output']Recursive tracing
Section titled “Recursive tracing”For code without explicit regions, or when function-level attribution is needed, opt in to recursive tracing:
%%bashscope-profiler run -q -o recursive.h5 --recursive app.pyregion_names("recursive.h5")['__main__.<module>', '__main__.main', '__main__.setup_mesh', '__main__.solve', '__main__.write_output', 'app.py', 'linear_solve', 'setup_mesh', 'write_output']--include and --exclude accept shell-style globs for recursively traced
function names. --all additionally includes installed packages and the
standard library:
%%bashscope-profiler run -q -o filtered.h5 --recursive \ --include 'my_app.solver.*' \ --exclude '*logging*' \ app.pyregion_names("filtered.h5")['app.py', 'linear_solve', 'setup_mesh', 'write_output']Use --entrypoint main to name the traced application entrypoint. Recursive
tracing has more overhead than explicit regions, so filters are recommended
for large applications.
%%bashscope-profiler run -q -o entrypoint.h5 --recursive --entrypoint main app.pyregion_names("entrypoint.h5")['__main__.<module>', '__main__.setup_mesh', '__main__.solve', '__main__.write_output', 'app.py', 'linear_solve', 'main', 'setup_mesh', 'write_output']Python lifecycle shortcuts
Section titled “Python lifecycle shortcuts”The CLI is equivalent to a managed Python session. For a callable entrypoint,
use sp.run():
def main(): with sp.region("step"): time.sleep(0.001)
sp.run(main, output="profile.h5", verbose=False)Use the session decorator when the application should own its entrypoint:
def run_application(): with sp.region("step"): time.sleep(0.001)
@sp.session(file_path="profile.h5", verbose=False)def main(): run_application()
main()For a script that cannot use a context manager, opt in to a guarded exit hook:
run = sp.setup(file_path="profile.h5", auto_finalize=True)The exit hook finalizes when the interpreter exits. This notebook finalizes explicitly instead, which cancels the pending hook:
sp.finalize(verbose=False)Output and summaries
Section titled “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:
%%bashscope-profiler run -q -o profile.h5 app.pyscope-profiler run -q -o profile.json app.pyscope-profiler run -q -o report.html app.pyscope-profiler run -q --no-output app.pylsapp.pyentrypoint.h5filtered.h5profile.h5profile.jsonrecursive.h5report.htmltagged.h5Use --label to identify a run in comparisons:
%%bashscope-profiler run -q --label baseline app.pysp.read_h5("profiling_data.h5").display_label'baseline'Concurrency
Section titled “Concurrency”Thread and asynchronous task tracking are opt-in Python API modes:
from concurrent.futures import ThreadPoolExecutor
def worker(index): with sp.region("worker"): time.sleep(0.001)
def run_parallel_work(): with ThreadPoolExecutor(max_workers=2) as pool: list(pool.map(worker, range(4)))
async def main(): with sp.region("task"): await asyncio.sleep(0.001)
with sp.session(track_threads=True, verbose=False, output=None): run_parallel_work()
# A notebook already runs an event loop: in a script this is `asyncio.run(main())`.with sp.session(track_async=True, verbose=False, output=None): await 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
Section titled “Reducing trace volume”Aggregation mode stores counts and timing totals without per-call events:
%%bashscope-profiler run -q -o aggregated.h5 --aggregation-mode app.pyFor periodic workloads, pause profiling between phases or use
sample_every():
class Simulation: def step(self): with sp.region("step"): pass
simulation = Simulation()steps = 100
with sp.session(file_path="profile.h5", verbose=False): with ProfileManager.sample_every(10) as profile_step: for step in range(steps): with profile_step(step): simulation.step(){region.name: region.num_calls for region in sp.read_h5("profile.h5").get_regions()}{'scope_profiler.session': 1, 'step': 10}Only every tenth step is profiled: 10 of the 100 calls of step are recorded.
See Configuration for line profiling, GPU timing, NVTX, MPI, LIKWID, memory profiling, and HDF5 tuning options.
Notebook workflows
Section titled “Notebook workflows”Load the IPython magics when profiling from a notebook:
%load_ext scope_profiler.ipython_magicsUse %%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.