125 points f311a 2 hours ago 58 comments

bratao 1 hour ago | parent

This is pretty bittersweet to see.

Python is my favorite language, but I'm honestly tired of having to rewrite performance bottlenecks in Cython or Rust all the time. When the Faster CPython project started with Microsoft's backing, I was really excited. Mark Shannon had that plan promising huge speedups across a few cycles, and while that clearly turned out to be much harder than anticipated, the team still kept pushing forward to deliver a real JIT.

Seeing all of that get bogged down in committee bureaucracy now is just frustrating.

I have a lot of respect for the core devs and I know maintaining CPython, and it is a time donation job. It isn't easy. But I feel that over-caution and red tape ends up discouraging serious contributions. They are setting an unreasonably high bar for something that would obviously help the entire ecosystem.

Just think about the sheer amount of electricity and compute power being wasted every single day running inefficient Python across millions of machines worldwide.

Python really deserves a proper JIT. I genuinely hope they reconsider this.

mananaysiempre 1 hour ago | parent

Unladen Swallow died for lack of upstream interest.

PyPy lacks upstream interest, looked like it could have a shot after many years of development but recently NumPy removed support because they just couldn’t fathom how a non-dead project could be a couple of minor versions behind CPython.

Now the new JIT is dying because of what seems to be a lack of upstream interest. (The things TFA describes as being required are not unreasonable, but not realistic for a necessarily speculative long-running project without wild amounts of committed funding.)

I’m not optimistic.

pansa2 42 minutes ago | parent

> Unladen Swallow died for lack of upstream interest

IIRC Unladen Swallow was, despite the extreme hype, nothing more than the internship project of a couple of students. It died because their internship was over.

Otherwise you're right, though. Lots of CPython alternatives suffer from lack of upstream interest - the Python language designers don't seem very interested in anything other than CPython. In particular, they appear to only consider CPython when adding features to the language. Two examples:

- Requiring `dict`s to be ordered because that's how they work in CPython, without considering how they work in other implementations

- Adding pattern matching syntax that's suitable for CPython's PEG parser, even though it's not LL(1) so can't be parsed by, say, MicroPython

ZiiS 1 hour ago | parent

I know not everyone loves them; but `Claude rewrite the performance bottlenecks in Rust` works so well it is hard to see the security surface area and harder reason about performance as something that should be paid in core.

greenavocado 31 minutes ago | parent

ddorian43 13 minutes ago | parent

Seems unmaintained from July.

xx_ns 1 hour ago | parent

It's unfortunate that a technically exciting new feature is being killed partly because of what is essentially bureaucracy (and the lack of the developer's personal bandwidth). On the other hand, it's pretty safe to say that the strict adherence to the PEP policy and all of the bureaucracy that comes with it is what makes Python a great language, for better or worse.

Not to say that the technical objections were without merit, they likely very much weren't, and the debugger and instrumentation support and maintenance work sounds fairly painful on its own.

Good4boothee 1 hour ago | parent

Looking at amount of JIT related (for example type confusion) security bugs in V8 I am not surprised other developers are vary of its inclusion.

jeremyjh 1 hour ago | parent

I think it would be a mistake to conclude this has anything at all to do with bureaucracy as a matter of inanimate policy that the SC was helplessly in thrall to. Bureaucracy was the tool the SC used to demonstrate that this feature lacked many important properties that they cared about, as mentioned: "maintenance, compatibility, and ... clear success metrics". For whatever detailed reasons, the PEP was withdrawn after it couldn't convincingly demonstrate those things to the satisfaction of the critics on the SC.

bunderbunder 49 minutes ago | parent

Im not sure I even like calling it bureaucracy. It’s a process, yes. But we’re not talking many layers of abstract organizational hell, here. Were talking a fairly direct process of documenting what you are doing and how you are going to do it well enough that others working and depending on the project can understand it, coordinate with it, and have a reasonable degree of confidence that it won’t cause undue problems.

If having to put all that in writing and get a bunch of people to agree feels too burdensome to you, maybe that’s a sign that you would be happier working on something other than core changes to the world’s second most popular programming language.

(edit: That wasn’t meant to be a jab at the core developers working on the JIT. Based on what’s in the public discussion threads, they have been handling things very well throughout the process. It’s unfortunate that the SC let the project get this far before realizing the project had grown well beyond its original PIP’s mandate, and I’m sure that is deeply frustrating to the people leading the project. I know I would not be handling the setback nearly as gracefully as they are.)

vlovich123 17 minutes ago | parent

The problem is that clearly documenting all details as required in the PEP is at odds with complicated new features like a JIT where all the details can’t be known and have to be decided on as they are realized. Process / bureaucracy is at direct odds with experimentation.

jeremyjh 1 minute ago | parent

What are you basing this statement on?

kannanvijayan 1 hour ago | parent

Gonna dump a technical hot take here.

Python is a mature production language with a lot of users. Even before it was huge - like 20 years ago when I was in college - getting a small backwards compatible API change into a python extension module (gnu readline in my case) required convincing GvR personally that the API change was necessary.

Every JIT attempt I've seen for python just tries to cut too deep in the first pass, and scope themselves too large.

I believe any successful attempt at optimizing python performance from JIT will FIRST start with a 100% semantically compatible hidden type model for optimizing object property access and method dispatch.

The single biggest performance delta in most dynamic language jits come from that, not from optimizing guards off of bytecode operations or from compiling to machine code. It's from converting hashtable lookups into constant-time guard + offset lookups.

The hidden type model is also a hard nut to crack. It needs to perserve dict semantics which have very dynamic behaviour via the various `__*__` methods, and handle exotics scope objects since scoped name lookups are the most common ones which have their own exotic behaviours (I remember python providing some ability for callee frames to inspect caller scopes in some limited ways).

Pxtl 1 hour ago | parent

It still blows my mind that the big "we're breaking backwards compatibility Python 3000" release didn't do anything to lay the groundwork for this, or any of Python's other structural problems.

jeremyjh 1 hour ago | parent

Its possible this could have been the concrete pillar that broke the camel's back and set Python 3 on the path of Perl 6.

ModernMech 1 hour ago | parent

At the time, Python had a clear purpose as an easy to learn "glue" language between other, perhaps more performant languages. There was no reason to make Python as fast because that would muddy its purpose by introducing compromises and complexity. For better or worse Python sat pretty well in its niche.

Today there are far more people using it, and everyone has a different perspective on what it is. No longer is it a niche glue language, now it's a backbone of AI technology at major tech firms, so it's understandable they'd like it to be faster on its own.

0xpgm 48 minutes ago | parent

For a long time Guido wanted CPython to remain simple, as the reference implementation.

Probably also during the 2 to 3 migration, but that goal appears to have now been abandoned.

I wonder how the authors of other implementations like pypy will be able to keep up as the reference implementation becomes more and more complex.

adrian17 1 hour ago | parent

> It's from converting hashtable lookups into constant-time guard + offset lookups.

Python already does it in a lot of cases, see opcode specializations like LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_SLOT.

kannanvijayan 20 minutes ago | parent

I haven't kept up with python development lately, so thanks for pointing that out. I looked this up and it does seem like some sort of property access is being optimized. What's not clear is what the hidden runtime type model is being used for this, or if it's a lightweight tracking that captures some subset of property accesses.

More digging led to this: https://peps.python.org/pep-0659/ which seems to be what the effort is organized around?

Python's object semantics are broadly similar to Javascript, bar the prototypical inheritance chain, but with the extra complexity of potentially needing to handle dynamic `__*attr__` overrides. Optimizing for this would require a tree of hidden map objects much like JS JIT engines use. I dug around the codebase a while back looking for something like that but didn't find it. `OrderedDict` seemed promising but after more investigation that turned out to just be adding property ordering to dictionaries.

The thing is, you can build that entire hidden type structure out, AND optimize against it, without ever having to mess with things like bytecode replacement. Once you have the hidden type model, you can modify the property lookup algorithm in the VM itself (as in cpython c code) to use some annotation structure hanging off of the bytecode to look up inline caches of type-guarded fastpaths. It would be an optimized fastpath that integrated directly into the C code that interprets the GETATTR opcode.

adrian17 4 minutes ago | parent

> Optimizing for this would require a tree of hidden map objects much like JS JIT engines use.

I don’t really think that’s true or even that relevant here, especially if a class has slots.

> The thing is, you can build that entire hidden type structure out, AND optimize against it, without ever having to mess with things like bytecode replacement.

Pretty sure the motivation was exactly the opposite - that a simple “if a LOAD_ATTR encounters the same class with slots N times in a row, swap it out for LOAD_ATTR_SLOT, and swap back to generic one something changes” is way easier than any alternative that’d interact with the object model. (Also it means you skip having to branch between a slow and fast path at all)

> you can modify the property lookup algorithm in the VM itself (as in cpython c code) to use some annotation structure hanging off of the bytecode to look up inline caches of type-guarded fastpaths. It would be an optimized fastpath that integrated directly into the C code that interprets the GETATTR opcode.

Sorry, that sounds a bit vague and not too different from what CPython already is doing.

graemep 1 hour ago | parent

If you look at the reasons for this it seems like a good decision: https://discuss.python.org/t/pep-836-jit-go-brrr-the-path-to...

There are already many way of addressing Python performance (leaving aside whether Python is a good choice if performance matters) such as Cython, Numba, Pypy and C extensions.

pbronez 1 hour ago | parent

Interesting, makes sense. JIT in CPython main is a big deal, glad they’re proceeding with caution. Overall looks like they added it as an experimental feature for two years, then decided to back it out. Perfectly reasonable outcome.

anthk 1 hour ago | parent

The Rust based Python3 port can keep it and it can still be far more secure than CPython. Not everything it's JIT'ted on RustPython, it's ondemand per function, you have to enable it explicitly.

adrian17 1 hour ago | parent

Unfortunate. I've been following the work on it occasionally.

On one hand, it seemed like JIT work was really progressing in high gear until SC requested a new PEP. Also unfortunate, as it seemed like part of the hope for the JIT was that it'd counter the performance penalty from free threading.

On the other, it did feel (to me) like with all the fancy (and definitely cool) optimizations it got (automatic refcount operation removal, new type-based specializations, inplace math operations), the macrobenchmark benefits weren't _that_ exciting for a JIT. It definitely has potential for more, maybe with even fancier optimizations like unboxing ints, but the complexity just keeps going up.

> It said that the PEP was "overly optimistic" about user-visible differences with the JIT enabled.

The JIT is technically generated from the same source as the interpreter loop itself, so originally the differences were extremely unlikely, but I imagine the risk just kept going up as new JIT-only paths and optimizations were introduced.

And politically, I feel like SC’s reasoning was just “this side project has landed in main branch almost by accident and has been stewing without oversight ever since, with no stabilization in sight”; and the latest PEP was probably still too vague, with a lot of “here’s more things we can add to the stew” - so I can understand if SC wasn’t satisfied.

Krishansubudhi 1 hour ago | parent

I hope it does not lead to performance issues later. Python is already famous for being slower than compiled languages.

FranOntanaya 41 minutes ago | parent

Being slower than a compiled language is not saying much for an interpreted language. But it's slower than PHP which is a closer comparison, and PHP has had JIT for six years now.

pansa2 30 minutes ago | parent

Ruby has the reputation of being a very slow language, but Python has been slower still since Ruby jumped ahead with version 1.9, almost 20 years ago. Ruby also has had far more success with JIT compilers than Python has.

chao- 8 minutes ago | parent

>Ruby also has had far more success with JIT compilers than Python has.

Ruby is on its third (I think?) JIT now? I'm a little surprised, given Ruby's reputation as a wacky "anything goes" language with a very complex grammar, and it makes me wonder why that is? Does it have to do with the design of the runtime itself more than the language semantics? Or is it more incidental, e.g. many popular ibs are C wrappers, already generates bytecode files, and so on.

tweakimp 1 hour ago | parent

Sad to read this. I had hoped that with the advance of AI capabilities, features like this could be prototyped, tested, implemented and shipped even faster. And I was really looking forward to see performance gains for my favourite language.

Where do we go from here? Microsoft did not continue to finance the Faster CPython project and the current speed gains are good, but not what we hoped.

Retr0id 55 minutes ago | parent

At this point if you have a python codebase where perf is an issue, the "AI-pilled" answer is to rewrite it in a faster language.

tweakimp 50 minutes ago | parent

But I want to continue to understand the code. I dont know Rust (maybe AI can teach me?) and if I let Claude rewrite my current 50k LOC project in Rust, how can I understand what is happening and how can I work on it and think it further?

Yossarrian22 2 minutes ago | parent

You could try having it rewrite parts of the hot path into Rust with PyO3.

lemagedurage 43 minutes ago | parent

It's already typical to call into a native library with Python bindings for performance critical work in Python. Even Pydantic's validation runs in Rust code.

Retr0id 8 minutes ago | parent

This works well if there are obvious "hot loops" that can be easily isolated, but sometimes the perf issues are more uniformly distributed throughout a codebase.

Eji1700 54 minutes ago | parent

A biased opinion as I dev in F#, but it strikes me that AI is going to play best with functionally pure languages (strongly typed, no side effects, whatever we call that these days)?

F# is on the softest side of that, but letting the compiler tell the AI "nope, here's why" seems like a huge win in saving cycles and time.

The downside at first was simply, "how many examples of F# are there to learn from", and early on it showed, but I think that's been long overcome.

And F# is obviously NOT the best example since it's both "soft" on functional purity and niche. I imagine something like haskell is probably doing even better, although I've yet to check that at all (not that I can code haskell but I haven't looked at anecdotes or anything).

I realize this doesn't really help anyone who's grown to love python, and there's surely no perfect language, but just like how the web catapulted javascript, I see a future where the answer isn't "use AI to make python better" so much as "what already works super well with AI, and does it ease the user adoption"

mhh__ 1 hour ago | parent

It seems like such a failing and waste of human life that we spend all this time waiting around for python when the JS engines are so cutting edge.

btown 1 hour ago | parent

From https://discuss.python.org/t/pep-836-jit-go-brrr-the-path-to... :

> We want the PEP to be clear that it’s ultimately the JIT team’s responsibility to find solutions for these packages and tools, and how to deal with situations where a tool can’t be supported or made to work

Is it just me or is this absurdly impossible, to the point of willfully killing the project? Committing a team of brilliant compiler engineers to doing free consulting ad infinitum for every bit of tooling in the world, however hacked-together?

The alternative would be to have the bravery to say: this is the way forward to keep this language relevant into the future, and as a steering committee we collectively own that some tooling may be out of date. Instead, this is a signal that Python is going to rest on its laurels for a very long time.

lemagedurage 52 minutes ago | parent

Given that the speedup is modest (~10%) and the Python 3 migration caused enough pain for users, I get it though. If it was a 2x speedup it would be a different story IMO

pansa2 1 hour ago | parent

Surprising, even though (IIRC) the performance of the JIT was always fairly underwhelming.

What about the other major change to Python's implementation: free threading? Has it lived up to expectations? I assume it's not also in doubt, despite Guido recently saying "Personally I wish we’d stuck with the GIL"? [0]

[0] https://discuss.python.org/t/pep-805-safe-parallel-python/10...

yxhuvud 9 minutes ago | parent

Getting a JIT from underwhelming to actually good is always going to be a whole lot of iterative work to remove blocking parts of the existing implementation. In Ruby-land we have had a good JIT for a while now, but it took many release cycles and a ton of resources before it was able to outperform the non JITed version when using Rails. Don't expect quick fixes that make great strides and any investments in it needs to be persistent and apply over time.

It boggles my mind that it apparently is the case that such a popular language as Python isn't able to get the resources to do this.

bilsbie 1 hour ago | parent

What’s the latest on getting rid of the GIL? Did that work out?

pansa2 1 hour ago | parent

> we don't feel we have the personal bandwidth to carry the current version forward

Are the JIT developers the same people who were working on Faster CPython at Microsoft? No surprise that they don't have the same amount of energy to dedicate to the JIT now that it's gone from a full-time job to a hobby project.

raverbashing 1 hour ago | parent

What's the status of 'Faster CPython'?

I wouldn't be surprised if they all went nodejs instead :/

Ralfp 48 minutes ago | parent

While JIT is being dropped, the original proposer and leader of the initiative was hired by ARM and continues work on speeding up Python.

His current focus seems to be speeding up GC and free threading.

tweakimp 48 minutes ago | parent

Microsoft is not financing it any more and laid off most of the team working on it.

claudiojulio 52 minutes ago | parent

It doesn’t matter. Just write it in Rust. AI will make Python less relevant in the future.

mike_hearn 50 minutes ago | parent

A sad day for CPython but it doesn't have to be a sad day for Python. There is a fully maintained implementation of Python 3.13 that has an advanced JIT compiler. Once your Python warms up it can be 4x faster or higher (depending on what your program is doing). That implementation is called GraalPy and it builds on the JVM:

https://graalpy.org/

A bit like Chrome there's a fully open source version and a proprietary version with a few extra bells and whistles, but the latter is entirely free for both open and commercial usage (you can't redistribute it for a fee). So you may as well use it.

It has other interesting features

• Scalable pauseless GC

• Single binary distribution of Python programs (like Go)

• Fancy and optimized interop with other languages including Java, JavaScript, Kotlin, Ruby and any other Truffle language.

• Supports native extensions. Tested and works with common libs like SciPy, NumPy, PyTorch, Pandas etc: https://graalpy.org/python-developers/compatibility/

• They're working on a GIL-free mode

In recent weeks there has been a release of a new web framework for Python that only runs on GraalPy, called Pyronaut (https://pyronaut.io/). It takes advantage of JVM interop to expose the Micronaut framework, which is similar to Spring for those who know it. Thanks to the JIT and well optimized base libraries it runs extremely fast, being about 3x faster than FastAPI+Granian, or 7x faster than Flask+Gunicorn and having many more features.

https://www.youtube.com/watch?v=zo6L7bxn4OY

(that was presented at Devoxx but the Pyronaut devs will start touring Python specific conferences soon)

So although CPython may not have made it past the JIT milestone, that doesn't mean Python as a language or community has to fail it. It does require openness to alternative implementations, but historically Pythonistas have been fairly good about that (e.g. Pypy was embraced back when it was more active).

This stuff does require you to accept that it's made by Oracle, but as it's open source, that should be OK.

Disclosure: I sit next to some of the people who work on this stuff.

titzer 22 minutes ago | parent

> Once your Python warms up

How long does that take?

mike_hearn 12 minutes ago | parent

The Pyronaut performance page has some graphs with the warmup parameters specified precisely:

https://pyronaut.io/performance/

> Latency lines come from the load ramp (+25% per 15-second step); throughput from 45-second validation steps (+2% each) after a 180-second warm-up. Each framework ran twice and we show its best run. No profilers were attached.

So that's a "realistic" web serving benchmark if you're willing to grant the use of a GraalPy-optimized framework rather than Flask/FastAPI.

Warmup times for other benchmarks are currently quite unstable because there's a big focus on interpreter performance at the moment, which is one of the main influences on warmup. There's a blog post here from August about how the compiler is being taught to recognize and optimize bytecode interpreter loops, to get results that normally require handcrafted assembly:

https://medium.com/graalvm/escaping-the-giant-switch-dec20b5...

So as you know already, warmup was historically a weakness of PE based stuff - although in this case the fair comparison is with CPython which never warms up at all - but a fast interpreter will make a big difference. In some benchmarks the GraalPy interpreter is already faster than the CPython interpreter, which is heavily optimized.

faangguyindia 33 minutes ago | parent

I just use Go and Rust for everything; most of my mobile apps are in Flutter. I don't see any point in using anything else.

for me it's over for python

O5vYtytb 31 minutes ago | parent

What a shame. The alternative is CinderX? It's slower unless you stick to "Static Python" which is not most python code in the wild.

phonon 30 minutes ago | parent

kibwen 27 minutes ago | parent

Assuming that the biggest bang-for-buck of JIT compilation is optimizing hot loops (which is also the biggest bang-for-buck of optimization in every other context as well), and assuming that, per the historical best practices, all hot loops in Python are already written in C (or Rust, these days), this outcome is somewhat what I would expect.

procaryote 9 minutes ago | parent

The performance of python indicates otherwise. There are some performance critical libraries written in C or C++ but a lot of python is written in python.

Python in itself is poorly suited to ever become performant as it lacks the types required. I imagine that causes some issues for effective jit-ing too.

They had a chance to fix this when adding type annotations, but instead of making it "optional/gradual typing" they opted to make it "documentation or linting support", which is obviously the wrong choice, but there were cultural reasons

rich_sasha 16 minutes ago | parent

Here’s an idea instead (maybe it already exists). Allow a decorator for writing inline Cython. It solves, I think, 90% of the problem. On first run, or eagerly, compile the decorated functions. Basically, Cython is the JIT, and user enables it explicitly.

This way I can easily write inlined functions with proper C speed, in a Python esque language.

Reasons why I rarely use Cython without this:

- unmodified Python code running in Cython is often faster, but not that much. 50% or so is my rule of thumb.

- but the development style is very different for Cython and Python, adding a lot of impedance. Eg reloading doesn’t quite work, profiling is different, you need a build directory and a build step at deployment etc.

- Cython proper is different enough and I’d argue unintuitive enough that if I have to have all these things in place, I might as well wrap my function in Rust.

Such a decorator would give you a low friction way to make things faster when you need it, with scope for making it much faster via all the funny Cython, while keeping Python-esque semantics, in particular "development semantics".

I think it would require some language modification since Cython was definitely a superset of Python; I think some of that syntax has been streamlined, but maybe still a strict superset.

ttul 1 minute ago | parent

I built this in 2001 (https://pyinline.sourceforge.net/). Obviously, that ancient thing doesn't work anymore, but the idea worked then and it ought to work today. That being said, I think there are significantly superior options in existence now!

alerighi 11 minutes ago | parent

I would not like a JIT to be embedded in python for one reason. The sole reason why Python didn't have all the security related bugs of other languages (just think about all the exploits in JS engines, as well as the recent PHP vulnerabilities) is sorely because it's an interpreted language, that is python is compiled in a bytecode that runs in a VM.

Under these premises is very difficult that something not implemented correctly is really exploitable, and moreover it's simple to verify the security of the whole thing.

Opening a JIT, that would mean mapping memory pages as RWX, would open the door to all soft of exploits that now are not really possible.

CGamesPlay 7 minutes ago | parent

> just think about all the exploits in JS engines, as well as the recent PHP vulnerabilities

Can you name some of these JS engine vulnerabilities? And the PHP one had nothing to do with JIT.