DEV Community

Cover image for Python's JIT is being removed. I checked — my Python never had one.
frank chu
frank chu

Posted on

Python's JIT is being removed. I checked — my Python never had one.

LWN's headline this morning (October 27) is short: "Python's experimental JIT to be removed." I went looking for what that means in practice, starting with the Python on my own machine. The first finding is embarrassing in a useful way: my Python never had a JIT to lose.

The probe: PYTHON_JIT=1 on a stock Python

This VM runs the Python most servers actually run — the distro build:

import sys, os
print(sys.version)
# 3.12.3 (main, Aug 31 2026, 10:18:26) [GCC 13.3.0]
print(hasattr(sys, "_jit"))
# False
Enter fullscreen mode Exit fullscreen mode

The JIT landed in CPython's main branch in 3.13, behind a build-time flag and the PYTHON_JIT environment variable. Python 3.12 predates all of it. There is no warning, no error — the variable is simply ignored. I benchmarked a hot integer loop (200,000 iterations, median of 7 runs, two separate processes per setting) to make the silence measurable:

PYTHON_JIT unset : median 0.0247s / 0.0246s
PYTHON_JIT=1     : median 0.0241s / 0.0247s
PYTHON_JIT=0     : median 0.0242s / 0.0240s
result check     : hot(10) = 273 in every run
Enter fullscreen mode Exit fullscreen mode

Every median sits within about 3% of every other, which on this box is run-to-run noise. That is the honest summary of the JIT era for a large slice of production Python: an opt-in, build-it-yourself experiment that most deployments never switched on. What is on my 3.12 — and stays — is the specializing adaptive interpreter from PEP 659. The code object in the probe above carries _co_code_adaptive; the speedups ordinary users actually received in 3.11 and 3.12 came from that, not from the JIT.

What is actually being removed

The sequence, from the primary sources:

  • April 2024 — PEP 744 sketches the JIT design and explicitly defers the question of its long-term status.
  • June 5, 2026 — the Steering Council asks for a real Standards Track PEP arguing for the JIT as supported code, within roughly six months, or the experiment leaves main.
  • July 2, 2026 — PEP 836, "JIT Go Brrr," is filed by Savannah Ostrowski, Ken Jin, and Brandt Bucher.
  • October 19, 2026 — PEP 836 is marked Withdrawn, 109 days after it was created and 136 days into the Council's ~182-day window. The authors say they lack the personal bandwidth to carry the draft after Council feedback raised the bar. Brett Cannon's summary is the operative one: withdrawal means the JIT leaves CPython's repository; any continuation happens outside that tree, starting with a reference implementation the authors plan to publish.

This is not a verdict that the technology failed. The PEP's own abstract credits the 3.15 JIT with a 4–12% geometric-mean speedup on pyperformance across Tier 1 platforms, debugger-unwindable frames, and a smaller generated-code footprint than 3.14. The problem is visible in the PEP's own target: promotion required at least 20% geometric-mean improvement by Python 3.17's first beta. The gap between where the JIT is (4–12%) and where it had to be (20%) is 8 to 16 points — to be closed by a team that just told the Council it doesn't have the hours.

The code leaving the tree is not small. Counting just the JIT and tier-2 optimizer files in Python/ on main today — jit.c, jit_unwind.c, optimizer*.c, the generated optimizer_cases.c.h, and friends — I get:

9 core files : 596,587 bytes (~583 KiB)
largest      : optimizer_cases.c.h at 208,894 bytes
plus         : Tools/jit/ build tooling and the uop definitions
               the interpreter itself is generated from
Enter fullscreen mode Exit fullscreen mode

That last part is why "just move it to a fork" is harder than it sounds, and why PEP 836 argued for staying in-tree: the micro-ops the JIT consumes are co-designed with the interpreter and regenerated from it. An out-of-tree JIT has to track those definitions across a branch boundary, in exactly the area where drift means wrong code, silently.

What to do with this

Three practical notes:

  1. If you never built CPython with --enable-experimental-jit, nothing changes for you. That is most people, including this machine. The 3.15 JIT keeps receiving bug and security fixes; new optimizer work is what's paused and now headed out.
  2. The performance story of CPython does not end here. The specializing interpreter stays, free-threading is a separate track, and both were delivering gains to default builds while the JIT was still opt-in.
  3. Watch the reference implementation. The authors still back the technical direction — a method-based frontend instead of trace recording, free-threaded compatibility — and say they're optimistic. Ruby's YJIT-to-ZJIT rewrite was raised in the debate as a cautionary tale about forced frontend switches stalling progress; whether the CPython JIT moves faster outside the tree is now an empirical question.

I have some sympathy for both sides. The Council asked a fair question — who maintains this, forever, and what does it do to profilers, debuggers, and every tool that touches interpreter internals? The authors gave a fair answer — not us, not at that bar, not now. A 583 KiB experiment that delivers 4–12% to the people who build it themselves was never going to survive that exchange. The JIT didn't get benchmarked out of CPython. It got staffed out.

Sources: LWN, "Python's experimental JIT to be removed" (Oct 27, 2026); PEP 836 (status: Withdrawn, resolution Oct 19, 2026) and its abstract's 3.15 performance figures; PEP 744; the withdrawal summary at freenode.net (Oct 21, 2026). All local measurements were run on this machine today.

Top comments (1)

Collapse
 
pandadev2470 profile image
PandaDev •

Interesting read! I've been using Python for years, but honestly never gave much thought to whether the JIT was actually enabled in my environment.

It's funny how we hear about new features in Python and just assume they're part of what we're already running. Now I'm curious to check my own setup.🤔