4 min read
Cost of tracemalloc: start/stop, take_snapshot, compare_to, and allocation slowdown while tracing. Measured on Linux localhost.
Related links:
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. Complements gc.collect cost (lab 129) — tracing overhead, not cyclic reclaim.
Verdict up front (n=20000 bytearrays): alloc without tracemalloc ~18152296 objs/s; with tracing ~1111095 (~16.3× slower). Hot snapshot ~7.28 ms (~137 snapshots/s).
| Arm | Pattern |
|---|---|
| start/stop | enable tracing briefly |
| start+alloc+snapshot+stop | one-shot profile |
| take_snapshot hot | tracing already on |
| compare_to lineno | diff two snapshots |
| get_traced_memory ×10k | cheap counters |
| alloc with/without tracing | slowdown |
Seven rounds, p50.
Script: lab-evidence/131-tracemalloc-snapshot/results/run_lab.py.
| Arm | p50 | rate |
|---|---|---|
| alloc without | 1.102 ms | 18152296 objs/s |
| alloc with | 18.0 ms | 1111095 objs/s |
| take_snapshot hot | 7.28 ms | 137 /s |
| compare_to | 158.312 ms | 6.3 /s |
| get_traced_memory 10k | 33.486 ms | 298632 calls/s |
| start_alloc_snapshot_stop | 27.038 ms | — |
Peak sample while tracing: 3891664 bytes (one-shot arm); loop peak 2593136.
Tracing made the alloc loop about 16.3× slower on this box. Leave tracemalloc off in production request paths; enable for canaries, repro scripts, or timed windows.
get_traced_memory stayed cheap (~298632 calls/s for the 10k batch) — fine for an occasional gauge if tracing must stay on.
compare_to (budget ~158.312 ms here).stop() in finally so a forgotten trace does not linger.Hot take_snapshot was ~7.28 ms; compare_to(..., "lineno") jumped to ~158.312 ms. Diffing is the expensive report step — do it offline or rarely.
The combined start → alloc → snapshot → stop path took ~27.038 ms end-to-end for 20000 allocations. That is acceptable for a canary or a failing unit repro; it is not a per-request tax. Prefer wrapping suspect code in a context manager that guarantees tracemalloc.stop() even on exceptions so workers do not silently stay in traced mode after a debug deploy.
Evidence: summary.json, summary.txt.
One Linux box. Default tracemalloc frames. Not fil / memray.
Keep a before/after RSS note alongside traced peaks — tracemalloc explains Python allocations, not every mmap or allocator arena, so on-call should not equate the two gauges.
Filter snapshot statistics to your package paths before paging a human — unfiltered lineno diffs are noisy on large apps.
Alloc under tracemalloc ran ~16.3× slower (~1111095 vs ~18152296 objs/s). Use snapshots for investigations; do not leave tracing enabled on hot paths.
Lab evidence
Lab 1 Oct 2026 IST. Python 3.13.5. n=20000 bytearrays: alloc slowdown ~16.3x; without tracing 18152296 objs/s, with tracing 1111095. Hot snapshot 7.28 ms; compare_to 158.312 ms; get_traced_memory 298632 calls/s. Affiliates: 0. Evidence: lab-evidence/131-tracemalloc-snapshot/.
Hands-on platform.platform vs os.uname host inventory lab: real ops/s plus cache notes, measured on Linux localhost today in this hands-on lab for SREs.
Summary1 Oct 20264 min read
Hands-on signal SIGUSR1 vs threading.Event wakeup lab: real p50 latency in microseconds, measured on Linux localhost today in this hands-on lab for SREs.
Summary1 Oct 20264 min read
Hands-on cmath vs math.hypot magnitude ops lab: real ops/s for abs, polar, and phase, measured on Linux localhost today in this hands-on lab for SREs.
Summary1 Oct 20263 min read