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 (0)