Rendered at 20:47:20 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
jakobnissen 2 days ago [-]
So not much progress since 3.14 - but still progress! Personally, I think it's nice when my code automatically gets faster thanks to someone else's work, and I don't understand all the negative sentiment in this thread.
Yes, of course Python is still a slow language. You hopefully knew that when you picked Python for your project.
scorpioxy 2 days ago [-]
I tend to describe it as "a language not optimized for raw processing speed" as opposed to being a slow language. As in, it is an abstraction that is meant to speed up development(and be easier to read etc) rather than be the fastest while running.
BerislavLopac 2 days ago [-]
Exactly. I like to say that Python is one of the fastest languages if you measure by metrics other than "raw processing speed". One very important metric is speed of development - and due to a combination of lack of the compilation step, its dynamic nature, ecosystem of libraries and clean syntax, very few languages can match Python in that regard.
pjmlp 1 days ago [-]
What is slow is CPython, not the language, but unfortunely PyPy, GraalPy and co, don't get much community love.
ModernMech 1 days ago [-]
It's like climbing a ladder to get to the moon. You can make steady, slow progress, but you're never going to get to the destination without drastically rethinking the entire approach.
scosman 2 days ago [-]
only tangentially related, but naming PyPy when PyPI was already established was ridiculous
zahlman 2 days ago [-]
Both names have sensible etymology ("Python [implemented in] Python"; "Python Package Index") and are pronounced differently (PyPI is "pie pee eye").
Not to mention that the PyPy name was established long before the initial release too. It was in development at least since 2003, under that name.
IIRC there was a PyPy talk at EuroPython 2003.
The first commit to the current repo is dated Feb 24, 2003, and the commit message is:
Move the pypy trunk into its own top level directory so the path names
stay constant.
...indicating there were previous history that got lost in the migration to hg or git.
In the next episode of Complaining About Names; Why did those silly South Americans give their forest the same name as Bezos' company? :-)
advenn 1 days ago [-]
for me, they are pay-pay (like pronouncing pie-pie) and pay-pi (sounds like pie-pe) :)
makaimc 2 days ago [-]
35 years on since the first public Python release and there's still so much room for improvement in its performance. These tests by Miguel are a useful quick check on that progress in 3.15 even if as he admits it's impossible to get "an objective and universal measure of the performance of a programming language".
JohnKemeny 23 hours ago [-]
This doesn't seem to test the GC, nor important operations such as dict lookup/iteration, set add/membership, list iteration and updating.
Is really a recursive implementation of Fib an enlightening benchmark? I don't think so. And bubblesort is just messing around with two pointers.
Why not, if you're first doing benchmarking, find out what the most time consuming popular operations/algorithms are, and then use them?
Now it seems that you are just testing two obscure algorithms that are not really representative for Python coding in general.
brianwawok 2 days ago [-]
So Claude can convert python code bases to rust or golang, and give you an easy 10x speed boost. Much better than waiting for Python performance to improve
ks2048 2 days ago [-]
For a lot of scripts (think replacement to bash scripts - perhaps even one-offs), Python will save time over rust compilation times.
nazcan 2 days ago [-]
Golang it is then! I'm really enjoying the fast compile time compared to C++...
skrtskrt 2 days ago [-]
And packaging + distribution is ridiculously easy.
We are moving every script we can to Go.
Compared to bash it's a no-brainer, every dev can understand it, it has approximately .0000000000001% of the possible footguns, a great debugger, etc.
masklinn 2 days ago [-]
At the scale of “bash scripts”, rust will compile instantly unless you’ve gone insane with dependencies
cogman10 2 days ago [-]
For one offs, sure. But once you get to a script executed multiple times it doesn't take very long before you have payed off the rust compile time. Especially if it is fairly simple (as in, you can do everything with just rust std lib and not a bunch of rust libs).
Almost all the rust compilation times come from needing to build the supporting libs. For simple scripts, it's very possible to get away with just using the std lib.
UnlockedSecrets 2 days ago [-]
At the same time, If a python script can be thrown together in 20 minutes, and it will execute hundreds of times at most..... Who really cares if it takes 25 seconds to execute, or 2 minutes as long as it accomplishes all it is intended to do?
cogman10 2 days ago [-]
In my opinion, what is pretty typical a script will be executed never, once, or thousands of times.
If you are at the point of doing multiple executions, you are probably at the point where converting your script to rust would end up saving time/power. Maybe not all the time (like a manually executed script), but not infrequently.
pjmlp 2 days ago [-]
There are D, Go, C#, OCaml as an option, not only Rust.
loeg 2 days ago [-]
Non-optimized builds can be pretty quick, although I guess you're always paying for borrow checking.
masklinn 2 days ago [-]
Being a local property, borrow checking is cheap. IIRC even Polonius is single digit percent in the worst case on crater runs.
sgarland 2 days ago [-]
There is a benefit in being able to read and understand your code. If you’re most proficient in Python, it’s reasonable to want to stay there, perhaps looking to PyPy.
Also, of course, the majority of SaaS apps (perhaps most apps in general?) are not compute-bound, so gains from performance alone shouldn’t be the only metric.
My current job has a mix of Python and Go. Personally, I dislike Go. I don’t like its syntax, I don’t like its utter lack of formatting standards (gofmt is not a standard; also it sets tabs - ugh), I don’t like its insistence on static linking, and I don’t like how people claim it’s a great scripting language when you can’t just run a file on its own (and its stdlib is weak sauce compared to Python).
killingtime74 2 days ago [-]
I can read rust much easier than go at least. If the Python doesn't have types then it's about even as well.
loeg 2 days ago [-]
Of course, Claude understands Rust, too.
winrid 2 days ago [-]
Rust is nice to read because you can see from a function signature what it mutates
If you write slow rust, it's very easy to read, and still plenty fast.
rtpg 2 days ago [-]
For a server using a DB, all of your methods are calling out to data stores. So you're like "OK I receive a &connection" but all the mutability is hidden inside.
There's a bunch of type direction you can do to get around this (`ReadConnection` vs `ReadWriteConnection` and some other magic), far from an immediate win but it's not impossible.
People talk about mutability a lot but the vast majority of Python code I see in the wild is SSA and has _very_ little mutability to begin with.
Of course ownership still has its costs. Lots of "I guess I'm copying this dict because I don't know if the owner will modify it or not" issues.
I think people overestimate how much they'll get from `&mut` annotations on business logic, and undersestimate how much line noise they'd get from a lot of the other stuff that happens in a lot of business logic.
Granted, I'm coming from a web-dev/Django perspective, where duck typing and overriding methods in subclasses is used heavily. And a lot of that doesn't have a nice 1:1 equivalent in the Rust model.
(I enjoy Rust BTW, just don't feel particular excitement about shuffling around strings in it)
winrid 5 hours ago [-]
not everyone is writing simple web servers :) and if you are, then the rust is easy to read as it's simple. I also use django in some large projects, and don't see a future of my use of django really anymore. If I'm not feeling like rust is a great fit, I usually reach for Java with javalin.
nomel 2 days ago [-]
Yeah, none of these tight loop benchmark tasks should be happening in python, which is why you won't see anywhere NEAR this kind of speedup with "normal" python code, that makes any attempt to use the many c python libraries that exists for these (like the built in sort functions, ffs).
Over the years, I've tried pypy and whatnot, but I've only ever seen between -30% and 30% speedups, depending on the code.
tclancy 2 days ago [-]
Why not convert to assembly?
chronogram 2 days ago [-]
Assembly doesn't add anything here. You'd still need to implement the IO, portability, safety, etc etc. You'd end up with the same thing so you might as well use Go from the get go. Assembly is useful for dedicated SIMD like in dav1d.
ChrisRR 2 days ago [-]
You mean compiling?
Izikiel43 2 days ago [-]
Portability
pmarreck 2 days ago [-]
Can’t wait for this to eliminate Python frankly. Too many scars from that unfortunate ecosystem
skeledrew 1 days ago [-]
Good luck. AI is built on Python, and it's just getting started.
dezsiszabi 2 days ago [-]
Answer: not fast at all.
keyle 2 days ago [-]
I'd go one step further: was never fast and can never be fast.
DroneBetter 2 days ago [-]
you should include a faster version of the fibonacci function with exponentiation by squaring
def fibonacci(k):
a,b=(0,1)
for i in range(k.bit_length()-1,-1,-1):
d=a**2
c=2*a*b-d
d+=b**2
(a,b)=(d,c+d) if k>>i&1 else (c,d)
return a
both of these would be more intensive on the arithmetic side rather than control flow
also you could at least wrap the existing one in a `functools.cache`
0123456789ABCDE 2 days ago [-]
the point of the benchmark is not to make `fib()` fast, but to exercise the code in ways everyone can understand. ex: `functools.cache` decorator would mostly show you how fast python `dict`s are — not very useful
miguelgrinberg 1 days ago [-]
The idea is not for the benchmarking scripts to be efficient. For this type of benchmark it does not really matter if the code is efficient or not, because I'm running the same code and comparing how it performs on different versions of the interpreter.
I mention in the article that the reason I like the Fibonacci script that I'm using is that it is extremely slow, because recursion in Python is very slow. The point is to track improvements for the class of algorithms that rely on recursion.
klooney 2 days ago [-]
I had kind of thought PyPy was dead, I'm glad to see they made it to 3.12
rurban 2 days ago [-]
2 benchmarks only? A very broad sense of coverage
perpetualpear 2 days ago [-]
The lazy imports are a reason to upgrade.
OutOfHere 15 hours ago [-]
I didn't see a benchmark for combined JIT with FT.
sieve 2 days ago [-]
I have been using Python for the past two years for various things. But it is criminally slow. I joke that using Python on your modern 2020s CPU upgrades it to a Pentium 4 from 2004 running code compiled with C. And the 2004 version might still be faster.
Yes, some of the syntax is nice. But the rest of it, the scoping rules, the obstinacy around the lambda syntax, the venv/pip nonsense, path resolution etc is a hot mess. Were it not for astral tooling like uv, I would have abandoned it in a few weeks.
I hate thinking about memory outside of very specific workflows, so I am willing to accept a 2-3x penalty over C for cleaner and shorter code that follows the happy path. But anything beyond that and you are wasting energy and people's time.
For Python to work as something other than a glue language where we write all critical code in C/Rust and call it from inside Python, something like PyPy is almost mandatory. But the design of the language, the exposed innards, and the need to maintain backward compatibility makes optimization a chore.
I did some benchmarking of Python against C, Go, Rust, Node, LuaJIT etc in preparation for my runtime.[1] My observations based on some stats:
- You can blindly replace C with Rust for most tested workflows. There is very little performance difference outside of compiler speed. (C23 is a nice language though.)
- Go is 2-3x slower than C
- Node and LuaJIT are 3-8x slower on average compared to C
- Python is 60-70x slower. It can get far, far slower in certain cases.
You can run your own benchmarks. I think you might end up in the same ballpark.
[1] I have been interested in reverse engineering, hobbyist compiler/VM development etc for a couple of decades and wondered what is the point of ranting for two years about it without doing anything concrete. So I decided to build a runtime and statically typed language borrowing stuff from Python and Erlang/BEAM. But, even with LLMs implementing my ideas faithfully, the last 20-30% is a never-ending process which means I get bored and move on to something I can finish in 3-4 days.
orojackson 2 days ago [-]
It also depends on what your use case is for the programs you write in those languages. If the use case relies heavily on CPU performance, then yeah, Python is awful in that regard. But if you're like me who mostly deals with ETL processes and report generation from several different systems over the internet, then Python's 60-70x slowdown means NOTHING in the face of network latency and the need to work with pagination limitations these external systems impose on REST endpoint users (and no, gRPC or its binary-serialization ilk are not available options).
Outside of that, though, what really grinds my gears about Python aside from its broad standard library compared to other languages is that it is home to what I think is the best property testing library in the world, Hypothesis. I know that the folks at Antithesis are working on getting Hegel [1] up and running, but they don't even have plans to support the language that my workplace prefers: C# (and I have been leading the charge in my workplace to keep up with the latest versions of .NET). Given how agents are now creating and modifying whole codebases, property tests live in that nice middle ground between unit tests and formal verification when it comes to validating (as best as we can) that the code works as intended.
Yes, the workflow matters. And it is one reason why Python is popular in the ETL and other processes. You are essentially offloading computation to efficient code while Python simply orchestrates. You probably spend one percent of the time inside Python itself, so it is pretty convenient.
I normally have one "tooling" language that I write all kinds of stuff in. And it goes beyond glue. So performance matters to me.
re: testing, I am pretty old-fashioned. I don't test everything. Only stuff that is critical or complex enough where I suspect breakage in the future. Also, I think borrowing ideas from Ada/Haskell/Clean etc for a new language could solve a lot of these pain points, now that LLMs are writing most of the code.
orojackson 2 days ago [-]
Pretty charitable to call Salesforce a bastion of "efficient code" hahaha
You're lucky to be able to control as much of the stack as you want with your one "tooling" language to rule them all so that performance matters again. Although in all fairness, given the regulatory and workplace culture as well as constrained budgets, sometimes you do have to let go of chasing performance in the name of making things easier for the maintainers at work. As I mentioned in a different post, it also helps to be working in a captive market, which helps relieve the pressure a bit.
Also, my Python ETL scripts do calculations for certain things, but attempting to speed that part up with a low level language like C or Rust doesn't really move the needle for total processing time when you have latencies measured in the hundreds of milliseconds per page of data. Scale that up to multiple pages and the whole runtime is dominated by how long it takes for packets to move from my Windows Server to Salesforce and back. It's basically a whole lot of effort for very little gain.
sieve 2 days ago [-]
Work is JVM. So not much space there. But I did manage to incorporate a tiny LISP-like language into my principal application to make some configuration tasks easier. Everything outside it, I can control.
I get your usage. If you never spend enough time in slow mode, there is no point moving the code elsewhere as the savings do not justify the labor.
My issue is that I do not want to use or maintain code in 10 different languages. A single language, even one that is 3-5x slower than C would work. My only asks are that it should:
- be performant
- have basic infrastructure (cryptography, database etc)
- be aesthetically pleasing to read and write
mroche 2 days ago [-]
> I did some benchmarking of Python against C, Go, Rust, Node, LuaJIT etc in preparation for my runtime.
Out of curiosity, have you seen if Cython[0] would provide any benefit to your runtime performance?
I looked at it briefly, but did not use it. I actually made an effort to use PyPy, but the issues I mentioned probably ensure that it will always lag behind CPython as far as language support is concerned.
The situation is tricky and the friction is considerable. It is not like JS where v8 made the existing language blazing fast with no changes to the language itself.
Would rather use something like Nim with Python-like syntax.
Drupon 2 days ago [-]
>I joke that using Python on your modern 2020s CPU upgrades it to a Pentium 4 from 2004 running code compiled with C. And the 2004 version might still be faster.
It really doesn't for a lot of the things that matter, and people should seriously ignore your opinions if you're making these kind of fatuous jokes. Any serious person should understand what CPU bound tasks are vs what IO bound ones are. Python is used for the latter, with some C/C++/Rust bindings for the former. You are ignorant and tedious. When should I actually give a fuck? is the question that you types that build nothing never manage to answer. If you can improve some significant metric by 50x by moving away from Python, you should be fired for having been stupid enough to choose the wrong tool for the job.
sieve 2 days ago [-]
> Any serious person should understand what CPU bound tasks are vs what IO bound ones are.
This is a decision fork only when you are stuck using a slow language. I don't have to do this --- at all --- when using C/Java and so many other languages.
Using Python as glue and writing extensions in C/Rust is a choice. But I'd rather write everything in C23 by that point. Or move to a faster language if syntax/aesthetics is an issue.
Further, you often do not have a choice on what platform you get to work with. Someone might have built an expensive-to-replace website using PHP. And then you have to build HipHop to speed it up.
bjourne 2 days ago [-]
My pet peeve are numbers with too many decimals. If you only run a benchmark three times and take the arithmetic mean you don't have five or more significant digits. At best, you have two. And for benchmarking the geometric mean is a far superior mean.
jrk 2 days ago [-]
For averaging multiple different benchmarks, the geometric mean makes sense. For removing measurement noise from a single benchmark, min or median is usually the right statistic.
PyPy dates to 2007 (older than Pip!); back then I'm pretty sure people were still calling PyPI the Cheeseshop, and it was still hosted on the main python.org site for years after that (https://packaging.python.org/en/latest/guides/migrating-to-p...).
Not to mention that the PyPy name was established long before the initial release too. It was in development at least since 2003, under that name.
IIRC there was a PyPy talk at EuroPython 2003.
The first commit to the current repo is dated Feb 24, 2003, and the commit message is:
...indicating there were previous history that got lost in the migration to hg or git.In the next episode of Complaining About Names; Why did those silly South Americans give their forest the same name as Bezos' company? :-)
Is really a recursive implementation of Fib an enlightening benchmark? I don't think so. And bubblesort is just messing around with two pointers.
Why not, if you're first doing benchmarking, find out what the most time consuming popular operations/algorithms are, and then use them?
Now it seems that you are just testing two obscure algorithms that are not really representative for Python coding in general.
We are moving every script we can to Go. Compared to bash it's a no-brainer, every dev can understand it, it has approximately .0000000000001% of the possible footguns, a great debugger, etc.
Almost all the rust compilation times come from needing to build the supporting libs. For simple scripts, it's very possible to get away with just using the std lib.
If you are at the point of doing multiple executions, you are probably at the point where converting your script to rust would end up saving time/power. Maybe not all the time (like a manually executed script), but not infrequently.
Also, of course, the majority of SaaS apps (perhaps most apps in general?) are not compute-bound, so gains from performance alone shouldn’t be the only metric.
My current job has a mix of Python and Go. Personally, I dislike Go. I don’t like its syntax, I don’t like its utter lack of formatting standards (gofmt is not a standard; also it sets tabs - ugh), I don’t like its insistence on static linking, and I don’t like how people claim it’s a great scripting language when you can’t just run a file on its own (and its stdlib is weak sauce compared to Python).
If you write slow rust, it's very easy to read, and still plenty fast.
There's a bunch of type direction you can do to get around this (`ReadConnection` vs `ReadWriteConnection` and some other magic), far from an immediate win but it's not impossible.
People talk about mutability a lot but the vast majority of Python code I see in the wild is SSA and has _very_ little mutability to begin with.
Of course ownership still has its costs. Lots of "I guess I'm copying this dict because I don't know if the owner will modify it or not" issues.
I think people overestimate how much they'll get from `&mut` annotations on business logic, and undersestimate how much line noise they'd get from a lot of the other stuff that happens in a lot of business logic.
Granted, I'm coming from a web-dev/Django perspective, where duck typing and overriding methods in subclasses is used heavily. And a lot of that doesn't have a nice 1:1 equivalent in the Rust model.
(I enjoy Rust BTW, just don't feel particular excitement about shuffling around strings in it)
Over the years, I've tried pypy and whatnot, but I've only ever seen between -30% and 30% speedups, depending on the code.
you can also encode polynomials into integers; see https://mathstodon.xyz/@peterluschny/116320199782572958 and the following prog from https://codegolf.stackexchange.com/a/279771
both of these would be more intensive on the arithmetic side rather than control flowalso you could at least wrap the existing one in a `functools.cache`
I mention in the article that the reason I like the Fibonacci script that I'm using is that it is extremely slow, because recursion in Python is very slow. The point is to track improvements for the class of algorithms that rely on recursion.
Yes, some of the syntax is nice. But the rest of it, the scoping rules, the obstinacy around the lambda syntax, the venv/pip nonsense, path resolution etc is a hot mess. Were it not for astral tooling like uv, I would have abandoned it in a few weeks.
I hate thinking about memory outside of very specific workflows, so I am willing to accept a 2-3x penalty over C for cleaner and shorter code that follows the happy path. But anything beyond that and you are wasting energy and people's time.
For Python to work as something other than a glue language where we write all critical code in C/Rust and call it from inside Python, something like PyPy is almost mandatory. But the design of the language, the exposed innards, and the need to maintain backward compatibility makes optimization a chore.
I did some benchmarking of Python against C, Go, Rust, Node, LuaJIT etc in preparation for my runtime.[1] My observations based on some stats:
- You can blindly replace C with Rust for most tested workflows. There is very little performance difference outside of compiler speed. (C23 is a nice language though.)
- Go is 2-3x slower than C
- Node and LuaJIT are 3-8x slower on average compared to C
- Python is 60-70x slower. It can get far, far slower in certain cases.
You can run your own benchmarks. I think you might end up in the same ballpark.
[1] I have been interested in reverse engineering, hobbyist compiler/VM development etc for a couple of decades and wondered what is the point of ranting for two years about it without doing anything concrete. So I decided to build a runtime and statically typed language borrowing stuff from Python and Erlang/BEAM. But, even with LLMs implementing my ideas faithfully, the last 20-30% is a never-ending process which means I get bored and move on to something I can finish in 3-4 days.
Outside of that, though, what really grinds my gears about Python aside from its broad standard library compared to other languages is that it is home to what I think is the best property testing library in the world, Hypothesis. I know that the folks at Antithesis are working on getting Hegel [1] up and running, but they don't even have plans to support the language that my workplace prefers: C# (and I have been leading the charge in my workplace to keep up with the latest versions of .NET). Given how agents are now creating and modifying whole codebases, property tests live in that nice middle ground between unit tests and formal verification when it comes to validating (as best as we can) that the code works as intended.
[1] https://hegel.dev/
I normally have one "tooling" language that I write all kinds of stuff in. And it goes beyond glue. So performance matters to me.
re: testing, I am pretty old-fashioned. I don't test everything. Only stuff that is critical or complex enough where I suspect breakage in the future. Also, I think borrowing ideas from Ada/Haskell/Clean etc for a new language could solve a lot of these pain points, now that LLMs are writing most of the code.
You're lucky to be able to control as much of the stack as you want with your one "tooling" language to rule them all so that performance matters again. Although in all fairness, given the regulatory and workplace culture as well as constrained budgets, sometimes you do have to let go of chasing performance in the name of making things easier for the maintainers at work. As I mentioned in a different post, it also helps to be working in a captive market, which helps relieve the pressure a bit.
Also, my Python ETL scripts do calculations for certain things, but attempting to speed that part up with a low level language like C or Rust doesn't really move the needle for total processing time when you have latencies measured in the hundreds of milliseconds per page of data. Scale that up to multiple pages and the whole runtime is dominated by how long it takes for packets to move from my Windows Server to Salesforce and back. It's basically a whole lot of effort for very little gain.
I get your usage. If you never spend enough time in slow mode, there is no point moving the code elsewhere as the savings do not justify the labor.
My issue is that I do not want to use or maintain code in 10 different languages. A single language, even one that is 3-5x slower than C would work. My only asks are that it should:
- be performant
- have basic infrastructure (cryptography, database etc)
- be aesthetically pleasing to read and write
Out of curiosity, have you seen if Cython[0] would provide any benefit to your runtime performance?
[0]: https://cython.readthedocs.io/en/latest/src/quickstart/cytho...
The situation is tricky and the friction is considerable. It is not like JS where v8 made the existing language blazing fast with no changes to the language itself.
Would rather use something like Nim with Python-like syntax.
It really doesn't for a lot of the things that matter, and people should seriously ignore your opinions if you're making these kind of fatuous jokes. Any serious person should understand what CPU bound tasks are vs what IO bound ones are. Python is used for the latter, with some C/C++/Rust bindings for the former. You are ignorant and tedious. When should I actually give a fuck? is the question that you types that build nothing never manage to answer. If you can improve some significant metric by 50x by moving away from Python, you should be fired for having been stupid enough to choose the wrong tool for the job.
This is a decision fork only when you are stuck using a slow language. I don't have to do this --- at all --- when using C/Java and so many other languages.
Using Python as glue and writing extensions in C/Rust is a choice. But I'd rather write everything in C23 by that point. Or move to a faster language if syntax/aesthetics is an issue.
Further, you often do not have a choice on what platform you get to work with. Someone might have built an expensive-to-replace website using PHP. And then you have to build HipHop to speed it up.