Pyinstrument: A Python Profiler
Pyinstrument: A Modern Python Profiler for Faster, Smarter Code
Introduction: What Pyinstrument Is and Why It Helps
Profiling is the disciplined practice of measuring where a program spends its time. Pyinstrument is a Python profiler designed to make that task approachable, actionable, and fast. In practical terms, Pyinstrument helps you locate the slowest parts of your code so you can focus your optimization efforts where they will deliver the biggest speedups. It’s not just about getting a number; it’s about surfacing a clear call tree and time distribution that tell a story about your program’s behavior under realistic workloads.
In practice, the most effective speedups come from removing bottlenecks in the critical path. Pyinstrument guides you to that path by presenting a readable profile with precise timing, call relationships, and a view into both Python and C function calls. If you’ve ever wondered “where is my program spending its time?”, Pyinstrument is the tool to answer that question.
Understanding profiling in simple terms: Amdahl’s law reminds us that the overall system speedup is limited by the portion of the code left unoptimized. Pyinstrument emphasizes the slowest parts of your program so you can focus your attention where it will matter most. It’s a practical companion for developers who want to transform code into faster, more responsive software.
Getting Started: Quick Install and First Run
- Installation: Pyinstrument supports Python 3.8 and newer. Installing is straightforward:
- pip install pyinstrument
- If you want to run Pyinstrument from a git checkout, there’s a build step you’ll follow (outlined in the contributing notes).
- Documentation: The official docs are the go-to resource for learning how to use Pyinstrument effectively, including a complete reference and tutorials.
Quick Start Checklist
- Ensure you’re using Python 3.8+.
- Install Pyinstrument with pip.
- Run a basic profile to see a report in your terminal.
- Explore the HTML report and interactive features for deeper insight.
How Pyinstrument Works: Core Concepts
- A lightweight, high-signal profiler: Pyinstrument collects samples over time to construct a call tree with timing information.
- Call trees and samples: At each sampling point, Pyinstrument notes which function is executing, building a tree that represents how much time is spent in each call and how code branches into deeper layers.
- Focus on live code paths: The profiler highlights code paths you actually execute, so you can understand real performance behavior rather than theoretical worst cases.
- Flexible renderers: Pyinstrument outputs to the console, HTML, and other formats, enabling easy sharing and visual inspection.
Where Pyinstrument Shines: Features and Capabilities
- Intuitive HTML timeline and call stack views: The HTML renderer presents a detailed, interactive view of the profile, including a timeline for zooming into moments of interest.
- Timeline mode for precise inspection: Timeline representations preserve ordering and allow for detailed exploration of repeated calls and nested frames.
- Console rendering with multiple modes: You can view a plain call tree in the console, or switch to a flat view to focus on the heaviest frames.
- Customization options for rendering: The renderer supports a variety of options, including thresholds and filters, to tailor the output to your needs.
- Integration with web frameworks and async code: Pyinstrument works with Django, FastAPI, aiohttp, and other frameworks, with options to customize filenames and behavior for saved profiles.
- Async support and modern Python features: The profiler adapts to asynchronous code, showing time spent both inside and outside await contexts.
- Export formats and data portability: Besides HTML and console views, Pyinstrument supports sessions that can be saved and loaded for later analysis, and even JSON-based rendering options.
- Easy profiling of code blocks and modules: You can profile specific chunks of code with a with block or decorator, making it convenient to test hypotheses and compare changes quickly.
- Lightweight, robust core: The core design minimizes overhead while ensuring accurate time accounting for both Python and certain C-level calls.
From CLI to Web: How to Use Pyinstrument
- Basic usage (CLI):
- pyinstrument script.py
- Profiling a specific code block:
- with a decorator or a with block, you can profile a chunk of code and see a short readout in the terminal.
- Rendering options:
- The HTML renderer produces interactive output, while the console output can be filtered or adjusted to show time in various units (absolute vs. percent of total).
- Extensions and integrations:
- Django middleware can be configured to describe targets and save or load profile data.
- FastAPI and other modern frameworks have dedicated guides and examples for profiling requests.
- Saving and loading sessions:
- You can save raw session data or rendered HTML, then reload later for comparison or sharing with teammates.
Selected Highlights from the Changelog: What’s New Across Versions
v5.1.2 (January 4, 2026)
Added the ability to customize the profile description via a CLI option --target-description.
Django middleware interval customization via PYINSTRUMENT_INTERVAL.
HTMLRenderer now supports preprocessors to modify the input call tree before writing HTML.
Bugfix: fix for mismatched start/stop sequences that could raise “call stack without an active session.”
The HTML renderer now limits the sample count to improve browser load times.
v5.1.1 (August 12, 2025)
Fixed several memory leaks in the low-level C extension.
v5.1.0 (August 10, 2025)
Printed durations adapt to the profile’s interval for greater detail at small intervals and reduced clutter at large intervals.
Django middleware: option to customize the saved profile filename via a callback.
Added an aiohttp.web example to the docs.
v5.0.0 (October 11, 2024)
Major improvements to the HTML renderer:
- Timeline mode for an interactive, zoomable linear timeline (a standout feature).
- HTML mode gains new interactive options, reducing the need for upfront configuration.
- Vue.js-based HTML renderer: faster, smaller bundles, and a smoother experience.
- Library code detection improved to reduce false positives by identifying Python install and active virtual environments.
Profiling API enhancements and broader environment support.
v4.x series (2019–2024)
A long progression of enhancements, including a shift to an HTML renderer with improved visuals, a new timeline feature, and better integration with Jupyter/IPython, and many bug fixes.
Early milestones introduced reflectors for more flexible rendering, support for Python 3.11, and new APIs for profiling chunks of code.
v3.x and earlier
Substantial refactors, improved module handling, and richer support for command-line options and Django middleware.
Early moves toward rendering improvements and better module exclusion logic to focus on application code.
Known Issues and Practical Workarounds
Profiling inside Docker can sometimes yield odd results:
The gettimeofday syscall Pyinstrument uses can be slow in Docker environments.
Workaround notes and issues are posted in the known issues section for visibility.
Pickle-based serialization with main:
If your script involves pickled classes and you profile via pyinstrument script.py, you may encounter issues related to main location. There are documented workarounds to address this scenario.
Async and multi-threaded scenarios:
While Pyinstrument supports async profiling, there are nuances when profiling in certain contexts; consult the async profiling documentation for best practices.
Visual Notes: Images That Complement the Experience
- The top badges and screenshot provide a quick sense of the project’s ecosystem and the kind of output you’ll see:
- PyPI version badge, CI badges, and a screenshot of the HTML/CLI outputs.
- In the article body, important illustrations show sample HTML representations and call trees:
- Timeline mode image (timeline.png) demonstrates how you can see and zoom into a profile over time.
- The gallery includes examples of call stacks, showing how library frames can be folded or presented differently to keep focus on your code.
- Inline images from historical versions depict how the UI evolved and how the renderer visuals improved over time.
- Specific visual references in the older changelog sections demonstrate the kinds of outputs you’ll interact with:
- A pair of images from the earlier HTML rendering and code structure: these help you understand how the profiler displays layers of function calls and which areas are highlighted as critical paths.
- An image showing an interactive flame chart-like view in speedscope and a browser-rendered timeline.
Contributing and Developing: How to Get Involved
- Development setup:
- Create a virtual environment with Python 3, activate it, and install dependencies from requirements-dev.txt.
- Use pre-commit hooks to enforce code quality (isort, black, pyright, etc.).
- Running checks locally:
- Run the full test suite with pytest.
- Run individual checks, like isort or black, to fix formatting locally.
- Exploring the HTML renderer:
- The HTML renderer is a Vue.js app embedded in the output. You can inspect and customize by editing the HTML renderer and rebuilding the JavaScript bundle.
- For development, you can serve the HTML renderer locally and see changes in real-time.
Community and Documentation
- Documentation is a central pillar of Pyinstrument’s usability. The docs include:
- A detailed guide on how the profiler works (including async profiling) and how to leverage different renderers.
- Usage examples for popular frameworks and environments (Django, FastAPI, Jupyter notebooks).
- A guide to profiling a web request, testing specific chunks of code, and working with timeline rendering.
- The project maintains a blog-like space that covers new features and best practices for profiling with Pyinstrument. If you’re curious about the rationale behind a particular feature (for example, the approach to async profiling or how to interpret HTML timelines), the docs and blog posts are excellent starting points.
Practical Tips for Getting the Most from Pyinstrument
- Start with a quick run to see the baseline profile, then iteratively profile smaller chunks of code to compare results.
- Use HTML timeline mode to identify long-running phases and then drill down into those segments with more granular sampling or targeted profiling.
- For web apps, profile specific endpoints using Django middleware or equivalent integrations to collect representative traces and compare across requests.
- When working with asynchronous code, pay attention to time spent outside await contexts to understand how your app spends time during I/O or waiting periods.
- Save sessions for cross-environment comparison (e.g., development vs. production) to understand how behavior changes across environments.
A Final Reflection: Why Pyinstrument Matters for Python Developers
Pyinstrument is designed for developers who want to move beyond guesswork toward precise, actionable performance insights. It merges a thoughtful, user-friendly interface with robust under-the-hood profiling techniques that are capable of handling modern Python code, including async and web frameworks. This combination—clear output, practical features, and evolving capabilities—helps teams deliver faster, more reliable software. The project’s ongoing development means that new renderers, improved accuracy, and better integration with contemporary tooling are continually on the horizon.
Images in this post
- PyPI version badge
- CI test badge
- Wheels build badge
- Screenshot
- Timeline image
- Old HTML rendering image
- Old HTML rendering image alt
- Speedscope/JSON viewer image
- Inner image showing timeline and call stacks
Whether you’re a new adopter or a long-time user, Pyinstrument offers a practical path to understanding and improving Python performance. The combination of accessible rendering, powerful features, and a clear roadmap for ongoing improvements makes it a compelling choice for developers who want to profile with confidence, iterate quickly, and ship faster, better software.
Enjoying this project?
Discover more amazing open-source projects on TechLogHub. We curate the best developer tools and projects.
Repository:https://github.com/joerick/pyinstrument
GitHub - joerick/pyinstrument: Pyinstrument: A Python Profiler
Pyinstrument is a modern, lightweight Python profiler that provides clear call trees and time distribution to help developers identify bottlenecks and improve p...
github - joerick/pyinstrument
