PEP 831 – Frame Pointers Everywhere: Enabling System-Level Observability for Python

Posted by mttd@reddit | Python | View on Reddit | 14 comments

https://peps.python.org/pep-0831/

This PEP proposes two things:

  1. Build CPython with frame pointers by default on platforms that support them. The default build configuration is changed to compile the interpreter with -fno-omit-frame-pointer and -mno-omit-leaf-frame-pointer. The flags are added to CFLAGS, so they apply to the interpreter itself and propagate to C extension modules built against this Python via sysconfig. An opt-out configure flag (--without-frame-pointers) is provided for deployments that require maximum raw throughput.

  2. Strongly recommend that all build systems in the Python ecosystem build with frame pointers by default. This PEP recommends that every compiled component that participates in the Python call stack (C extensions, Rust extensions, embedding applications, and native libraries) should enable frame pointers. A frame-pointer chain is only as strong as its weakest link: a single library without frame pointers breaks profiling, debugging, and tracing for the entire process.

Frame pointers are a CPU register convention that allows profilers, debuggers, and system tracing tools to reconstruct the call stack of a running process quickly and reliably. Omitting them (the compiler’s default at -O1 and above) prevents these tools from producing useful call stacks for Python processes, and undermines the perf trampoline support CPython shipped in 3.12.

The measured overhead is under 2% geometric mean for typical workloads (see Backwards Compatibility for per-platform numbers). Multiple major Linux distributions, language runtimes, and Python ecosystem tools have already adopted this change. No existing PEP covers this topic; CPython issue #96174 has been open since August 2022 without resolution.