Task runtimes#
collect_task_runtimes profiles a finished pipeline
run without any extra instrumentation: it walks every <task>_metadata dataset in a
butler collection, extracts the timing and memory fields with
from_task_metadata, and returns
a tidy per-task summary.
import lsst.daf.butler as dafButler
from lsst.analysis.ap import collect_task_runtimes
butler = dafButler.Butler("/repo/main")
df = collect_task_runtimes(butler, "u/me/my_ap_run")
# With a box plot of the per-quantum spread:
df, fig = collect_task_runtimes(butler, "u/me/my_ap_run", plot=True)
One row per task comes back, sorted slowest-first by total_time_max, with
n_quanta, the mean/min/max/std of total_time in seconds, and the same four
statistics for peak memory.
The memory columns are suffixed with their unit — memory_mean_GB or
memory_mean_MB — chosen once for the whole table (GB if any task crosses 1 GB) so
the numbers stay comparable down the column.
An empty run returns an empty DataFrame rather than raising.
threshold (default 1.0 s) filters out the noise, and it does so at task rather
than quantum granularity: a task is kept if at least one of its quanta reaches the
threshold, and then all of its quanta contribute to the summary.
That is what makes the mean/std meaningful — you see the task’s real cross-quantum
variability instead of a statistic computed only over its slow outliers.
# Only the tasks with a quantum taking 10 s or more.
df = collect_task_runtimes(butler, collections, threshold=10.0)
With plot=True the second return value is a matplotlib.figure.Figure holding a
horizontal box plot of per-quantum total_time, slowest task at the top, with the
threshold marked.
The x-axis switches to log scale automatically when the spread exceeds 100× the
threshold, which it usually does in an AP run.
Pass ax= to draw into an existing axes instead of a new figure.
Quanta whose metadata is missing an expected timing field — an aborted or killed run — are skipped rather than failing the call, so this works on a run that did not finish.