Python 3.12 ships with Meta-contributed runtime and typing features

With the release of Python 3.12, a set of features developed by Meta in collaboration with the Python community have landed in the upstream interpreter. The work spans reference counting, type checking, asyncio performance, and new runtime hooks intended for third-party JIT compilers and optimizers. Much of it builds on Meta's experience running Python at scale, particularly for the Instagram web-server workload.

Immortal Objects

PEP 683 introduces Immortal Objects: Python objects that do not participate in reference counting and live until interpreter shutdown. The feature was originally motivated by memory pressure in forking servers, where reference-count updates on shared objects trigger copy-on-write page duplication. Making frequently accessed objects immortal reduces that overhead. It also lays groundwork for truly immutable objects that can be shared between interpreters without locking, a step toward parallelism via multiple sub-interpreters or GIL-free threading.

Typing: new override decorator

The engineering team behind the Pyre type checker authored PEP 698, which adds a @typing.override decorator. Applied to a subclass method, the decorator tells static type checkers that the method intentionally overrides a base class method. If the base class is later refactored so that the overridden method no longer exists, the type checker can flag the now-dead code. This is intended to make inheritance hierarchy refactors safer and the codebase more maintainable.

Performance work

Inlined comprehensions

Previously, Python compiled every list, dict, and set comprehension as a nested function, allocating and destroying a one-use function object per execution. PEP 709 changes this by inlining comprehensions, which in the best case improves performance by up to two times. The implementation also exposed a pre-existing bytecode compiler bug in Python 3.11 that could produce silently wrong code; it was fixed as part of this work.

Eager asyncio tasks

Async functions often return a result immediately without ever needing to suspend. In those common cases, creating coroutine and Task objects and scheduling them on the event loop is pure overhead. Cinder, Meta's Python runtime, eliminates this cost with eager execution: an immediately awaited async function can return directly without creating a coroutine object, and an immediately awaited asyncio.gather() can resolve without creating Tasks at all if every gathered function returns immediately.

Full eager execution is too invasive a change for upstream Python and doesn't align with the TaskGroup API added in Python 3.11. Instead, Python 3.12 ships a simpler variant: eager tasks, opt-in via a custom task factory. The feature still creates coroutine and Task objects, but can skip scheduling the task on the event loop and resolve it immediately. Because it is a semantic change, it is not enabled by default.

Two smaller asyncio improvements also landed: a faster C implementation of asyncio.current_task, and an optimization to async task creation that shows gains of up to 5 percent on asyncio benchmarks.

Faster super()

A new LOAD_SUPER_ATTR opcode handles super().attr and super().method(...) without allocating a single-use "super" object on every execution. The overhead is now close to an ordinary attribute or method call.

Additional optimizations

Two hasattr optimizations and a 3.8x improvement to unittest.mock.Mock were also merged.

New benchmarks

Optimizing internal workloads is straightforward when production traffic is available to measure against, but open-source CPython work has no such reference point. To improve coverage of workload patterns Meta cares about, the team contributed new benchmarks to the Python Performance Benchmark suite:

  • An async_tree benchmark set modeling asyncio-heavy workloads.
  • Benchmarks exercising comprehensions and super(), which were previously under-represented in the suite.

Hooks for external JIT work

Cinder's JIT compiler and Static Python extensions are not intended for upstream CPython — they rely on limited platform support, C++ code, and semantic changes that are incompatible with the core interpreter. The plan is to ship them as an independent extension module called CinderX. That requires new extension points in the core runtime, several of which landed in Python 3.12:

  • An API for setting the vectorcall entry point of a Python function, giving a JIT a way to take over execution.
  • Watchers for dictionaries, types, functions, and code objects, letting a JIT invalidate its assumptions when dynamic changes occur.
  • Extensibility in the code generator for CPython's core interpreter, which allows Static Python to regenerate an interpreter with added opcodes.
  • A C API to visit all GC-tracked objects, helping the JIT discover functions created before it was enabled.
  • A thread-safe API for writing to perf-map files, so dynamically generated machine code can get human-readable names in the Linux perf profiler without conflicting with other JITs or Python 3.12's perf trampoline feature.

These hooks are aimed at anyone building a third-party JIT or runtime optimizer for CPython. There are also plans to use the watcher APIs internally in core CPython.

What comes next

Meta's Python involvement continues past this release. The company is in discussion with the Python Steering Council about PEP 703, which proposes removing the GIL to allow true multi-threaded parallelism — a potentially significant change for multi-threaded Python workloads.

Meta also continues to fund the Python Developer in Residence program, sponsor events such as PyCon US, and publish talks and engineering posts on Python compiler and runtime topics. Beyond language infrastructure, Python underpins Meta's Instagram server stack and is central to its AI/ML work, including the PyTorch framework.