Introduction
Pyinstrument is a statistical Python profiler that samples the call stack at regular intervals and produces a clean, readable tree showing where your program spends its time. Unlike cProfile, it focuses on wall-clock time and hides fast functions to surface the real bottlenecks.
What Pyinstrument Does
- Profiles Python programs with minimal overhead using statistical sampling
- Produces a call tree sorted by cumulative wall-clock time
- Hides fast functions automatically to highlight actual bottlenecks
- Supports profiling async code including asyncio coroutines
- Outputs results as text, HTML, JSON, or interactive speedscope format
Architecture Overview
Pyinstrument samples the Python call stack every millisecond using a C extension. Samples are aggregated into a call tree where each node's time represents wall-clock duration. The statistical approach means overhead is low (typically 2-5%) and results naturally emphasize slow code paths. An HTML renderer provides an interactive collapsible tree view.
Self-Hosting & Configuration
- Install via pip:
pip install pyinstrument - Run from the command line:
pyinstrument script.py - Use as a library with
Profiler()for fine-grained control - Integrate with Django via
MIDDLEWAREsetting for per-request profiling - Configure sampling interval with
--interval(default 1ms)
Key Features
- Clean tree output that highlights bottlenecks instead of listing every function
- Async-aware profiling that correctly handles await expressions
- Django and Flask middleware for profiling web requests with
?profileparameter - HTML report with collapsible tree and timeline visualization
- Export to speedscope JSON for flame chart analysis
Comparison with Similar Tools
- cProfile — Built-in deterministic profiler; shows function-level stats without tree context
- Scalene — Adds memory and GPU profiling; Pyinstrument focuses on readable call trees
- py-spy — Sampling profiler that attaches to running processes; Pyinstrument integrates into code
- VizTracer — Records every function call for timeline visualization; higher overhead than Pyinstrument
FAQ
Q: How is this different from cProfile? A: Pyinstrument measures wall-clock time and shows a call tree. cProfile measures CPU time per function in a flat list.
Q: What is the profiling overhead? A: Typically 2-5% due to statistical sampling, much less than deterministic profilers.
Q: Does it support async code? A: Yes. It correctly attributes time spent in async coroutines and awaits.
Q: Can I use it in production? A: The low overhead makes it viable for production profiling, especially with Django or Flask middleware.