|
|
Log in / Subscribe / Register

A pause for the Python JIT

By Joe Brockmeier
September 1, 2026

In 2024 the Python 3.13 release added an experimental just-in-time (JIT) compiler to optimize the way that CPython executes Python code. Since then, work has proceeded on the JIT, albeit perhaps less formally than some might like. In June, Python's steering council (SC) put out an announcement that no new development on the JIT land (with the exception of bug and security fixes) in Python's main branch, until it accepts a Python Enhancement Proposal (PEP) that would make the case for the JIT as a supported part of CPython. That has led to the creation of PEP 836 ("JIT Go Brrr: The Path to a Supported JIT Compiler for CPython"), which is currently under discussion. As it stands, it seems likely that work on JIT will continue, but when that will happen is less certain.

PEP it up

The Python community uses PEPs to propose new features, serve as a focus for discussion, collect community input, and to serve as a record of decisions. There are three types of PEP: standards track, process, and informational. The standards-track PEPs are for major new features or changes for Python, where the community needs to discuss and decide before (say) removing the global interpreter lock (GIL). Process PEPs are similar but are related to Python governance and development practices around the code base. If accepted by the steering council, these become binding, and (if applicable) work is to commence on implementing the proposal.

Informational PEPs are, as the name suggests, to provide guidelines or other information to the Python community; these PEPs do not represent formal consensus and are non-binding. As such, they generally would not be considered suitable as a basis of major new features landing in CPython's main branch, but work has proceeded on Python's JIT on the basis of PEP 744 ("JIT Compilation"), which is an informational PEP.

That PEP was only introduced several months after CPython core developer Brandt Bucher had already merged the pull request (PR) to add a JIT compiler in January 2024, ahead of the Python 3.13 release.

Thomas Wouters, a steering council member who was serving as the release manager for Python 3.13, stepped in a few days later and asked why the feature had been submitted before a PEP had been submitted or accepted. Ultimately, Wouters persuaded Bucher that a PEP was warranted, and he agreed to start work on one. PEP 744 was announced in April 2024. LWN covered some of that discussion at the time, and Bucher's PyCon US 2024 and PyCon US 2025 talks on the JIT compiler.

There is a "JIT Planning for 3.15 and 3.16" tracking issue on GitHub, created in September 2025, to track goals and work the JIT developers believe was needed to enable the JIT by default by the Python 3.16 release in 2027. But the work was continuing without a standards-track PEP that indicated larger community agreement and awareness.

Hit pause

In its announcement, the council took pains to note that it was not criticizing the JIT effort or those behind the work: "This has been hard, deeply technical work that has been done with great care, and the recent performance improvements are real and encouraging." However, because the project had been underway and undergone a few re-architectures, the council decided, "now is a good time to re-evaluate the JIT's informal status in the project".

The council set a window of six months for a new PEP to be submitted and resolved; it said that the JIT code is to be removed from the main branch and any development would need to continue outside that repository if a PEP is not accepted within that time frame.

We know this asks something of the people who have invested years in this work, and we don't take that lightly. We see this not as winding the project down but as giving it, and the community, the clarity and the explicit commitment that a change of this magnitude to CPython's runtime deserves.

The council asked that the PEP address several points; first, it should cover "how the JIT will be sustained and maintained over the long term". It would also need to explain how the JIT would keep compatibility with other CPython features and tooling, if the JIT would be compatible (or incompatible) with third-party JIT implementations, as well as whether the JIT architecture is considered stable or would change further. The council also asked for "clear, measurable success metrics and timelines"

Why now?

Naturally, there were questions about the announcement. Antoine Pitrou said that the council's decision seemed reasonable but wondered if there was "any further background" that prompted it. Wouters replied that there had not been "a single triggering request" for the PEP, but the announcement was released after the 3.15 beta to indicate the council was "okay with the status quo for 3.15". The JIT is still included as an experimental feature in 3.15 and includes major updates such as a new tracing frontend, a basic form of register allocation, and several optimizations.

Peter Bierma asked for clarification on the council's deadline: he thought that it was unlikely that it would be possible to meet the deadline when some PEPs, such as PEP 703 ("Making the Global Interpreter Lock Optional in CPython"), have taken five months to be accepted by the council after being formally submitted. Pablo Galindo Salgado indicated that the council would be flexible if the PEP was stuck in discussion or in its queue for consideration. Wouters added that the council was trying to drive a "clear decision from the community", because the JIT is a significant change that deserves serious attention. "That doesn't necessarily mean the JIT immediately gets ripped out when that six month deadline is hit – we're not unreasonable – but we do want this to be taken seriously."

The decision to stop development until a PEP is accepted, Mark Shannon said, put JIT contributors in an awkward position. He asked if work to improve the JIT could continue for a month or two "to give time for the PEP to be discussed properly". Council member and JIT contributor Savannah Ostrowski replied that she didn't think that the grace period Shannon asked for was necessary. "We understand the work is ongoing and the current state isn't the final state (as is true of most things in open source)."

Shannon clarified that he was worried about losing momentum and contributors. "There is other work I personally can do, on memory allocation and such, but PRs will bitrot and other contributors may lose interest." Jiahao Li, who had made contributions to the JIT, asked if there were "clear and minor optimizations" that might be acceptable to continue. Alyssa Coghlan suggested that a grace period might be warranted for any in-flight pull requests, especially those from new contributors. "Saying 'no new PRs on this topic until a PEP is approved' is one thing, shifting the goal posts for already in progress changes is something else".

Council member Donghee Na was not convinced that exceptions were a good idea. Even if the policy was adjusted to allow PRs that were already open, "I still think our main focus should be on writing the PEP. Involving those contributors in the PEP process would also be a good experience for them as part of CPython's development process."

On June 8, Diego Russo, a CPython core developer and JIT contributor, replied that he had discussed next steps with Shannon and they were working on a draft. The "JIT Go Brrr" draft PEP was announced on July 3 by Ken Jin. The PEP name may be a nod to the "doesjitgobrrr" web site that tracks the performance of the JIT versus the standard CPython interpreter. "Go Brrr" is a reference to a meme about the US Federal reserve printing money with a caption including the phrase "money printer go brrr".

New PEP

The PEP, authored by Bucher, Jin, and Ostrowski, lays out the current status for the JIT, as well providing a two-and-a-half year timeline with the milestones and goals for the JIT to become a non-experimental feature. The PEP leaves the decision of whether to enable the JIT by default to the Python release manager, rather than setting a condition for that to occur. Currently the JIT is included in the Python binaries for Windows and macOS, but it is disabled by default; some Linux distributions (the PEP cites Fedora and Gentoo) also include the JIT but leave it disabled by default. Interested users can turn on the JIT by setting PYTHON_JIT=1 as an environment variable.

The first year would be focused on developer-experience improvements, making the JIT compatible with free-threaded (no-GIL) Python, avoiding regressions, as well as adding further testing for native Python profilers and debuggers. The second year target, which is scheduled for the first beta of Python 3.17, is "at least 20% performance geometric mean improvement" measured by the Python Performance Benchmark Suite (pyperformance) when using the JIT and free-threaded Python versus free-threaded Python alone.

The last milestone, to be completed by the first 3.17 release candidate, is compatibility review: running the test suites of the top PyPI packages (exactly how many is not specified) to assess JIT compatibility with existing code.

The PEP also calls for adding support for multiple versions of the LLVM compiler; currently, building Python with the JIT enabled requires a specific version of LLVM. Building the JIT for Python 3.14 requires LLVM 19 and Python 3.15 requires LLVM 21; both versions of LLVM have reached end of life. LLVM is required because it is used to create templates called "stencils" (example) for the JIT.

There is a separate standards-track proposal, PEP 774 ("Removing the LLVM requirement for JIT builds"), that would remove the LLVM requirement entirely, but it has not yet been accepted. The current situation is a problem for Linux distributors that support versions of Python in long-term-support releases, as discussed in this thread on the Python forum.

The PEP also proposes some changes to the JIT's frontend infrastructure. Specifically, it calls for replacing the current trace-recording frontend of the JIT compiler with a method-based frontend to make the JIT easier to maintain and make it "more traditional and teachable", which is not the case now. "The current tracing frontend can produce head-scratching results even for very simple benchmarking programs." The trace-recording frontend is explained in detail in a blog post by Jin from May 2026.

Discussion

Cesare Di Mauro noted that the PEP mentioned that the JIT might use more memory, but it made no clear statement about the goals for memory consumption. Jin said that was a good point and planned to take it up with the co-authors of the PEP to include an upper limit on additional memory use.

Wouters, who clarified he was speaking as himself and not as a council member, thought that the PEP really felt like it was two PEPs: one that was showing the criteria for acceptance, and one that explained how the proposers expected to meet the criteria. "Fundamentally, the discussion about the minimum expectations for a supported JIT is distinct from how to get there, especially as we have different proposals for how to get there." He also questioned the firm timeline that was included in the PEP. "It's just not how development works in an open-source project, especially one that cares about backward compatibility."

He wanted to see an explicit discussion in the PEP about the JIT's startup time, warmup time, and memory overhead. These, he said, did not need to be "particularly strict numbers", but if those metrics were not tracked, it would not be possible to understand the cost paid when the JIT is enabled.

The other requirement he voiced was about maintainability of the JIT and its support among the core CPython team members. "We should focus on making whatever design we end up with understandable, and understood by the Core team. We need to make sure enough people work on it and spend time with it". Shannon agreed that "this seems like two PEPs", and implementation details in the current PEP seemed out of place.

Bucher replied the PEP was "providing what the SC asked for" and that the authors had put a lot of effort into creating a cohesive PEP. "A separate PEP seems like it makes the process more complicated and opaque, not less. Here, we have a way to present a complete story". He also thought that the current JIT "can be understood and is accessible to other members [of the community] outside the core team". Ostrowski added that it would make her uncomfortable to have the PEP include goals for the JIT without "everything we've thought through alongside it". Goals without plans, she said, aren't really goals at all.

Wouters responded that he understood where Bucher was coming from now. He added that his understanding of the council's request, though, was meant to be for the current JIT and not a future one. "If the plans in this PEP for the future JIT were rejected, that still leaves the fate of the current JIT unclear." Jin replied that the PEP was not proposing a new or future JIT, though it might seem that way for those unfamiliar with the recent JIT progress. "The design we described might seem like a radical change, but most of it is already in the current CPython main branch! Again, the only change is growing support for methods."

CinderX is an extension for improving the performance of the Python runtime that includes a JIT. Kevin Newton, one of the contributors to CinderX, also thought the proposal should be two PEPs. More importantly, he believed that the PEP "very much understates the sizeable difference between a tracing JIT and a method-at-a-time JIT" and was glossing over some important details. He said that CinderX had already run into some of the problems that the JIT developers would face in replacing the current frontend. He also worried about the focus on simplicity:

JITs and dynamic language runtimes are some of the more complex pieces of software out there. I promise I'm sympathetic to having too little energy and contributors, and it makes sense that you would want the things you mention. But I worry that eschewing complexity in favor of making a JIT compiler "fit" in someone's head ultimately results in a JIT compiler not worth having.

Jin said that he appreciated Newton's expertise with CinderX and other JITs, but he disagreed that it would require a lot of changes to support methods for the current state of the JIT in CPython. The developers had not yet implemented "the usual complex things" yet, which meant that it would not be highly complex to switch between the two at this time. He also disagreed that there was a mandate to produce two PEPs from the steering council, and wanted to avoid putting the burden of doing so on the JIT developers.

The "this should be two PEPs" theme continued with a lengthy comment from CPython core developer Jeremy Hylton. He called for separate PEPs describing the design of the JIT, how various parts of the interpreter runtime interact, as well as one that would describe metrics, timelines, and maintenance plans.

Eric Snow, also a CPython core developer, pushed back against the "ongoing pressure" and expressed support for the JIT. He thought documenting the design and addressing concerns was worth doing but disagreed with blocking further development in the main repository. There was a risk, he cautioned, that making extended demands that seemed like busy work would drive away contributors and turn Python into a project "in which mostly only enterprise teams participate".

Russo said he had worked on the JIT almost since its inception and felt the work should continue; he did, however, support splitting the document into two PEPs. He thought that trying to cover everything in one PEP broadened the discussion and made it harder to reach consensus. "The Steering Council's requests can be addressed through multiple focused PEPs rather than trying to fit everything into one document. Once we have an agreed baseline, follow-up PEPs can evolve individual parts of the JIT independently."

Status

The discussion seems to have lost momentum, without any official statement from the council about whether it also feels there should be multiple PEPs or if it is satisfied with the current draft. There has been no commitment from any of the PEP's authors to split up the current document or produce new PEPs.

On August 17, Wouters posted a summary of the council's meeting from August 6. The summary noted that the council "had office hours" with the authors "discussing the state of the PEP and whether it answered the questions the SC asked in its request for a PEP", but did not elaborate on the results of that discussion. PEP 836 was listed as an agenda item for the council's next meeting, but minutes from that meeting have not yet been posted.

For now, the development of the JIT seems to be largely on hold. No one seems to be voicing direct opposition to the JIT work, just a fair number of people who are asking for more information and debating the details.



to post comments

A needed PEP

Posted Sep 2, 2026 11:05 UTC (Wed) by q3cpma (subscriber, #120859) [Link] (2 responses)

I find it helpful to formalize the goals and requirements of the project. Especially as I'm sure a lot of people were a bit disappointed by the initial numbers compared to Pypy.

I also wonder if they'll manage to make a useful JIT using LLVM outside of long running scientific workflows, as the compilation cost compared to lighter solutions (e.g. asmjit, GNU lightning) is very high; well, there's this idea of distributing stencils like pre-compiled shaders, so maybe it won't matter?

A needed PEP

Posted Sep 3, 2026 7:22 UTC (Thu) by danielthompson (subscriber, #97243) [Link] (1 responses)

I thought that the CPython JIT was a copy-and-patch design. A copy-and-patch approach generally means that the code gen is pretty light since it is simply combining pre-compiled stencils. In a copy-and-patch design tools like LLVM are used only when the JIT itself is built in order to construct the stencils.

A needed PEP

Posted Sep 3, 2026 15:16 UTC (Thu) by smurf (subscriber, #17840) [Link]

copy-and-patching stencils might result in a light codegen, but it also limits the availability of stronger optimizations.

My real world workhorse code (semi-random data mangling to translate between an external SQL server, in-memory and mongodb caches, and the local tool API) gets 3x speedup on Pypy. I seriously doubt that copy+patch can get CPython into that range.

Rock and a hard place

Posted Sep 2, 2026 13:38 UTC (Wed) by rtpg (subscriber, #114619) [Link] (1 responses)

This situation is really uncomfortable. On one hand CPython/Python as a whole benefits so much from clear PEPs and writing it all out. On the other the JIT is in the project, and writing a PEP from now on top of blocking existing work feels a bit like we're either documenting what's in the code already (-> do we need a prolonged PEP process?) or going to pretend the existing implementation doesn't exist (also a bit of an awkward thing)

Hope it all ends up somewhere reasonable. Good luck to everyone invovled

Rock and a hard place

Posted Sep 2, 2026 22:56 UTC (Wed) by NYKevin (subscriber, #129325) [Link]

Reading between the lines, my impression is that they did this because they did not believe a PEP would be written otherwise. Or at least, it would not be written in a reasonable amount of time. The SC appears to be taking the implied position that a (proposal, non-informational) PEP should have been written and approved months if not years ago. If I'm reading that correctly, then on the surface it sounds fair enough to start attaching serious consequences, given a reasonable timeframe for compliance.

But obviously I am not privy to whatever backchanneling may or may not have been going on during this period, so I can't evaluate how fair that really is. If this was dropped on the JIT folks with absolutely no warning whatsoever, then that feels a bit unfortunate (even if it is within the SC's right). Perhaps they could've reached out earlier, without positioning it as an ultimatum. Or perhaps they've already done that several times in private and nobody listened.

What about the "other" JIT?

Posted Sep 2, 2026 17:40 UTC (Wed) by smurf (subscriber, #17840) [Link] (13 responses)

There's this thing called "pypy".

So, does CPython really need to re-invent the wheel here … or what's the motivation? Wouldn't it be far more efficient to port whatever CPython features pypy is currently missing?

What about the "other" JIT?

Posted Sep 2, 2026 18:18 UTC (Wed) by Cyberax (✭ supporter ✭, #52523) [Link] (10 responses)

Pypy is a way more complicated project, it's not just a Python implementation but a generic JIT framework.

What about the "other" JIT?

Posted Sep 3, 2026 10:08 UTC (Thu) by q3cpma (subscriber, #120859) [Link] (3 responses)

Might be true, but I've been lamenting the lack of such official and more detailed explanation from the cpython JIT effort. Because from an outsider view, it looks like tribalism and/or NIH syndrome.

One major reason, from memory, is that Pypy eschews the refcounting to go full tracing GC (good for performance!), which messes with deterministic destruction in some cases like context managers (the "with" statement), I think.

What about the "other" JIT?

Posted Sep 6, 2026 5:05 UTC (Sun) by NYKevin (subscriber, #129325) [Link] (1 responses)

You've got it backwards. The whole point of the "with" statement is to avoid the need for deterministic garbage collection. __exit__() is invoked when control leaves the block, regardless of whether the context manager sticks around afterwards. This lets Python emulate C++ RAII in cases where it is useful, without developers needing to deal with the cognitive overhead of manual memory management.

It's basically identical to Java's try-with-resources statement, and Java certainly does not have deterministic or predictable garbage collection.

What about the "other" JIT?

Posted Sep 13, 2026 9:33 UTC (Sun) by q3cpma (subscriber, #120859) [Link]

Yes, brainfart, indeed. Not about what "with" does (we got them everywhere in CL) but with the way these interact with strange stuff (like raise in the finally clause, I don't remember the exact catch; maybe https://peps.python.org/pep-0343/#:~:text=reference-counting)

What about the "other" JIT?

Posted Sep 6, 2026 11:37 UTC (Sun) by musicinmybrain (subscriber, #42780) [Link]

You may be thinking of the __del__() magic method, which was sometimes (ab)used for RAII-style resource management prior to the introduction of context managers in Python 2.5. This was passably deterministic in practice with CPython reference-counting, but not necessarily on alternative implementations like Jython.

What about the "other" JIT?

Posted Sep 3, 2026 14:49 UTC (Thu) by smurf (subscriber, #17840) [Link] (5 responses)

I know that Pypy has a lot more moving parts than if it was just a Python interpreter with a JIT add-in.

On the other hand: getting CPython into a state where running JITted code is actually useful in production (i.e. has a nontrivial speed advantage) might well result in something that's similarly complicated … not to mention, require a whole lot more effort than forward-porting the missing features of Py3.12+.

What about the "other" JIT?

Posted Sep 3, 2026 18:57 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (4 responses)

"More moving parts" is a huge understatement. It had a restricted dialect of Python that you use to write an interpreter that then gets JIT-ed as it does the interpretation.

What about the "other" JIT?

Posted Sep 3, 2026 19:49 UTC (Thu) by daroc (editor, #160859) [Link] (3 responses)

I made a personal project a while back that uses the Futamara projections to turn pypy into an ahead-of-time Python compiler. It was not usefully faster for practical programs and had extremely slow compilation times, but it was a neat trick. I called it pypypypy, naturally.

https://en.wikipedia.org/wiki/Partial_evaluation#Futamura...

What about the "other" JIT?

Posted Sep 3, 2026 21:35 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (2 responses)

That is horrible. I would love to see it!

What about the "other" JIT?

Posted Sep 4, 2026 15:35 UTC (Fri) by daroc (editor, #160859) [Link] (1 responses)

The code broke when pypy migrated to python 3, but I'll take a stab at it this weekend to see if I can get it working again and share it.

What about the "other" JIT?

Posted Sep 7, 2026 12:21 UTC (Mon) by daroc (editor, #160859) [Link]

Here it is: https://github.com/setupminimal/pypypypy

The code is terrible and uncommented and the generated binaries are not meaningfully specialized, but it does work.

What about the "other" JIT?

Posted Sep 3, 2026 19:01 UTC (Thu) by mb (subscriber, #50428) [Link] (1 responses)

CPython is the most Python compatible implementation by definition.
Therefore, it's not surprising that people also want it to be fast.

What about the "other" JIT?

Posted Sep 4, 2026 6:12 UTC (Fri) by smurf (subscriber, #17840) [Link]

I know that.

The problem is that the way to make it fast is a JIT-first architecture — as demonstrated by a couple of other scripting languages. Or Pypy.

Bolting some JITtishness into it … not so much.

IMHO.


Copyright © 2026, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds