Skip to content

PEP 799: A dedicated profilers module for organizing Python profiling tools #4504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ peps/pep-0792.rst @dstufft
peps/pep-0793.rst @encukou
peps/pep-0794.rst @brettcannon
peps/pep-0798.rst @JelleZijlstra
peps/pep-0799.rst @pablogsal
# ...
peps/pep-0800.rst @JelleZijlstra
peps/pep-0801.rst @warsaw
Expand Down
148 changes: 148 additions & 0 deletions peps/pep-0799.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
PEP: 799
Title: A dedicated ``profilers`` package for organizing Python profiling tools
Author: Pablo Galindo <pablogsal@python.org>,
László Kiss Kollár <kiss.kollar.laszlo@gmail.com>,
Discussions-To: Pending
Status: Draft
Type: Standards Track
Created: 21-Jul-2025
Python-Version: 3.15
Post-History:

Abstract
========

This PEP proposes the creation of a new standard library module named
:mod:`!profilers` to organize Python's built-in profiling tools under a single,
coherent namespace.

This PEP also proposes the deprecation of the :mod:`profile` module, a legacy
pure-Python tracing profiler.

Motivation
==========

Python currently ships with two tracing profilers: ``profile`` and ``cProfile``. The
``profile`` module is implemented in pure Python and is largely educational or useful for
subclassing, but too slow for realistic use. ``cProfile``, by contrast, is implemented
in C and more suitable for practical profiling scenarios, although it is not a drop-in
replacement for ``profile`` due to some behavioral differences.

Both of these are tracing profilers, meaning they instrument every function call and return.
This methodology introduces significant runtime overhead and can disable certain interpreter
optimizations, such as those introduced by :pep:`659`. Moreover, ``cProfile`` only observes the
main thread, making it less useful in modern concurrent Python programs. Confusingly, the naming
of these modules implies that ``profile`` is canonical, when in fact it is largely obsolete.

With Python 3.15, a new sampling profiler was introduced under ``profile.sample``. Known as
**tachyon**, this tool uses statistical sampling to infer performance characteristics, which
introduces much lower overhead and works better with the modern Python interpreter. It also supports
multiple threads, async functions, and attaching to running processes. Despite these strengths,
the placement of tachyon under ``profile.sample`` is misleading and obscures its importance.

Currently, the organization of profiling tools lacks a consistent, discoverable structure.
The proposed reorganization is meant to guide users more effectively toward appropriate tools,
clarify methodological distinctions between profilers, and lay the groundwork for future extensions.

Rationale
=========

This reorganization addresses several long-standing issues with Python’s profiling tools.

First, it improves **discoverability** by collecting all built-in profilers
under a single, clearly named namespace. Currently, profiling tools are
scattered across modules with inconsistent naming and unclear relationships. By
introducing the ``profilers`` module, users will have a well-defined and
intuitive location to explore and access profiling functionality.

Second, the proposal enhances **clarity** by naming the submodules according to
their underlying methodology -- ``profilers.tracing`` for deterministic tracing
profilers and ``profilers.sampling`` for statistical sampling profilers. This
explicit categorization makes it easier to understand the behavior and
limitations of each tool and aligns the API with the mental model users are
encouraged to adopt.

Third, it provides **guidance** to developers by making the recommended tools
easier to find and use. The current structure can mislead users into relying on
outdated or less performant modules like ``profile``, simply because of naming
precedence. With the ``profilers`` namespace and its clearer semantics, users
are more likely to choose the appropriate profiler for their specific use case,
whether it involves low-overhead sampling or detailed tracing.

Finally, this structure promotes **extensibility**. By consolidating profiling
tools under a unified namespace, it becomes straightforward to introduce future
profiling capabilities -- such as memory profilers, I/O profilers, or hybrid
tools -- without overloading unrelated modules or adding redundant top-level names.
The ``profilers`` module provides a natural home for this.

Specification
=============

New Module Structure
--------------------

This PEP introduces a new ``profilers`` module containing:

- ``profilers.tracing``: an alias for ``cProfile``, providing deterministic function-call tracing.
- ``profilers.sampling``: an alias for ``profilers.tachyon``, improving visibility and semantic clarity.

Additionally the **code** for the ``tachyon`` profiler will be also relocated to
the module as ``profilers.tachyon``.

Deprecation of ``profile``
--------------------------

The ``profile`` module will be deprecated starting in Python 3.15.

- In Python 3.15: importing ``profile`` emits a ``DeprecationWarning``.
- In Python 3.16: all uses of ``profile`` emit a ``DeprecationWarning``.
- In Python 3.17: the module will be removed from the standard library.

From Python 3.15, :mod:`!profilers.tracing` will be preferred to :mod:`!cProfile` & :mod:`!profile`.

The code that as the time of writing this is in :mod:`!profile.sampling`
module no longer exist and will only exist in the :mod:`!profilers` package.

Documentation
=============

The Python documentation will use the new :mod:`!profilers` module as the canonical
entry point for profiling functionality. It will also describe the distinction between
tracing and sampling profilers, and include guidance on when each type is most appropriate.

Documentation for ``cProfile`` and ``profile.sample`` will remain available but will link to
the new ``profilers`` equivalents.

Backwards Compatibility
=======================

The only backwards incompatible aspect of this PEP is the future removal of the ``profile`` module
but this will be made following the :pep:`387` procedure.

Security Implications
=====================

None.

Rejected Alternatives
=====================

Renaming ``cProfile``
---------------------

Renaming ``cProfile`` to ``profile.tracing`` was considered, but this change would impact a
large amount of existing code. Maintaining the original name while aliasing it under
``profilers.tracing`` strikes a balance between compatibility and clarity.

Top-Level ``tachyon`` Module
----------------------------

Introducing ``import tachyon`` as a new top-level module was rejected. Grouping tachyon under
``profilers`` helps establish a logical structure and prevents proliferation of top-level modules
and also minimizes the usage of global namespace as requested by the Python Steering council

Copyright
=========

This document is placed in the public domain or under the CC0-1.0-Universal
license, whichever is more permissive.