Pyinstrument
P

Pyinstrument

Pyinstrument

7,947 stars
N/A forks
N/A contributors

README

Project documentation from GitHub

Pyinstrument: A Low Overhead Python Profiler That Doesn’t Get in Your Way

If you’ve ever tried profiling a Python application, you know the pain. The standard profilers (like cProfile) give you mountains of raw data, but figuring out what’s actually slow usually requires staring at call trees for way too long. And the overhead? It can change the behavior of your code, making the profile misleading.

Enter Pyinstrument. It’s a statistical profiler that records call stacks at intervals, not every single function call. That means much lower overhead and results that actually reflect how your code performs in real life. It outputs something you can actually read without a PhD in Python internals.

What It Does

Pyinstrument is a Python profiler that samples the call stack at a regular interval (default is every millisecond). Instead of instrumenting every function call, it takes snapshots of what the program is doing. This gives you a profile that shows you which functions are taking the most wall-clock time, not just CPU time. So if your code is waiting on I/O, network, or sleeping, Pyinstrument shows you that too.

It also handles multi-threaded programs decently, and it can profile code running in different interpreters like PyPy or even inside a Jupyter notebook.

Why It’s Cool

The big thing is the output format. Pyinstrument gives you a tree where the most time-consuming paths are collapsed and sorted. The default console output looks like a nice, clean list of “here’s where the time goes” rather than an endless wall of numbers. You get:

 _ ._ __/__ _ _ _ _ _/_ Recorded: 16:45:42 /_//_/// /_\ / //_// / //_'/ // Duration: 1.23s
/ _/ v4.2.0 1.23s <module> __main__.py:1
├─ 0.84s some_slow_function my_module.py:10
│ ├─ 0.50s inner_loop my_module.py:15
│ └─ 0.34s another_call my_module.py:20
└─ 0.39s setup utils.py:5 └─ 0.39s read_file utils.py:12

It also supports rendering to HTML (with interactive flame charts), JSON, and even speedscope format for use with other tools.

Another neat feature: it works with async code. Because it’s sampling based, it doesn’t get confused by await points. That’s a real hassle with most profilers.

How to Try It

Install it with pip:

pip install pyinstrument

Then profile any script:

pyinstrument my_script.py

Or use it as a context manager in your code:

from pyinstrument import Profiler profiler = Profiler()
profiler.start() # Your code here profiler.stop()
print(profiler.output_text(unicode=True, color=True))

Did you like this issue?

Join our weekly newsletter

Love discovering amazing projects?

Help us continue bringing you the best open-source discoveries every week.

Back to Projects
Last updated: May 24, 2026