Saving output of timeit lets you capture detailed timing results in a variable for further analysis, comparison, or logging — instead of just printing them to the console. In Jupyter notebooks, the -o option with %timeit (or %%timeit) stores everything in a TimeitResult object — mean, standard deviation, best/worst times, all runs, loops, and repeats — giving you full access to statistics for scripts, reports, visualizations, or automated benchmarks. In 2026, saving timeit output is standard for reproducible performance testing, regression detection in CI/CD, comparing implementations, and tracking speed over time in production notebooks.
Here’s a complete, practical guide to saving and using timeit output: line and cell magic syntax, accessing attributes, real-world patterns, visualization, and modern best practices for accurate, actionable benchmarking.
In line magic mode (%timeit -o), timeit runs the single statement/expression and returns a TimeitResult object you can store and inspect.
import numpy as np
def dot_product():
x = np.random.rand(10000)
y = np.random.rand(10000)
return np.dot(x, y)
result = %timeit -o -n 1000 -r 5 dot_product()
print(f"Mean: {result.average * 1e6:.2f} µs ± {result.stdev * 1e6:.2f} ns")
print(f"Best: {result.best * 1e6:.2f} µs")
print(f"Worst: {result.worst * 1e6:.2f} µs")
print(f"Number of runs: {result.runs}, loops per run: {result.loops}")
print(f"All times (µs): {[t * 1e6 for t in result.all_runs]}")
In cell magic mode (%%timeit -o), timeit times the entire cell (multi-line code, loops, functions) — perfect for benchmarking larger blocks or functions with setup.
%%timeit -o -n 100 -r 7
total = 0
for i in range(10000):
total += i ** 2
# result = _ # In notebook, last expression is stored in _
print(f"Mean: {result.average * 1e3:.2f} ms ± {result.stdev * 1e3:.2f} µs")
Real-world pattern: comparing multiple implementations — save outputs, extract stats, and visualize differences for clear decisions.
def list_sum(data):
return sum(data)
def loop_sum(data):
total = 0
for x in data:
total += x
return total
data = list(range(100_000))
list_result = %timeit -o -n 500 -r 5 list_sum(data)
loop_result = %timeit -o -n 500 -r 5 loop_sum(data)
print(f"sum(): {list_result.average * 1e6:.2f} µs ± {list_result.stdev * 1e6:.2f} ns")
print(f"loop: {loop_result.average * 1e6:.2f} µs ± {loop_result.stdev * 1e6:.2f} ns")
# sum() is typically 5–10× faster — saved results let you compare reliably
Best practices make saved timeit output accurate, comparable, and actionable. Use -o to store results — access result.average (mean seconds), result.stdev (variability), result.best (fastest run), result.worst (slowest), result.runs (repeats), result.loops (executions per run), and result.all_runs (raw times). Control -n (loops) and -r (repeats) — high -n (10k–1M) for fast code, lower -n (100–1000) and higher -r (7–20) for slower code. Modern tip: plot results — use matplotlib/seaborn to visualize mean ± std dev vs input size for scaling behavior. In production notebooks, save outputs to variables, log them (logging.info), or export to CSV — track performance over commits or data sizes. Combine with profilers — timeit shows total time; line_profiler or cProfile show where time is spent. Prefer generator expressions over lists — sum(x**2 for x in range(n)) avoids list creation. Avoid timing in debug mode — use release settings, disable assertions, and warm up JIT if using PyPy/Numba.
Saving timeit output turns raw timings into analyzable data — mean gives speed, std dev shows reliability, best/worst highlight extremes. In 2026, use -o, control -n/-r, visualize scaling, and log results. Master saved timeit, and you’ll benchmark accurately, compare fairly, and optimize confidently — the foundation of fast, scalable Python code in interactive environments.
Next time you run %timeit or %%timeit — add -o and save the result. It’s Python’s cleanest way to turn performance numbers into insights.