Live data from Hacker News

Performance hacks for faster Python code

blog.jetbrains.com

21–30 of 65 posts

Re: Performance hacks for faster Python code

#21

(2) surprised me a little. Not because of the performance consequences, but because I almost never see explicit calls to `copy()` in Python (and I read a lot of Python). I think maybe a more realistic example there would be people using splatting without realizing/internalizing that it performs a full copy, e.g. xs = [1, *ys] Another one that stood out was (3). Slots are great, but >95% of the time I'd expect people…

I didn't find 2 surprising either, but I'm a little surprised you never see it. If you want to treat the args to a function as immutable, what can you do besides copy, modify, and return a new object?

Re: Performance hacks for faster Python code

#22
post #18
post #2

Maybe also knowing when not to use python, or finding a solution in python that uses C/rust/etc underneath.

It's kinda funny how uv is written in Rust and many Python libraries where performance is expected to matter (NumPy, Pandas, PyTorch, re, etc.) are implemented in C. Even if you call into fast code from Python you still have to contend with the GIL which I find very limiting for anything resembling performance.

Python's strong native story has always been one of its biggest draws: people find it ironic that so much of the Python ecosystem is native code, but it plays to Python's strength (native code where performance matters, Python for developer joy/ergonomics/velocity).

> Even if you call into fast code from Python you still have to contend with the GIL which I find very limiting for anything resembling performance.

It depends. A lot of native extension code can run without the GIL; the normal trick is to "detach" from the GIL for critical sections and only reconnect to it once Python needs to see your work. PyO3 has a nice collection of APIs for holding/releasing the GIL and for detaching from it entirely[1].

[1]: https://docs.rs/pyo3/0.27.1/pyo3/marker/struct.Python.html#m...

Re: Performance hacks for faster Python code

#23
I'm sure this is plenty useful for less experienced people, but the "smart" hacks read a bit like:

Hack 1: Don't Use The Obviously Wrong Data Structure For Your Problem!

Hack 2: Don't Have The Computer Do Useless Stuff!

Hack 3: Don't Allocate Memory When You Don't Need To!

And now, a word from our sponsor: AI! Use AI to help AI build AI with AI, now with 15% more AI! Only with AI! Ask your doctor if AI is right for you!

It's worth pointing out that a few of them are Python-specific. Compilers can inline code, there's usually no need to manually inline functions in most languages, that's Python being Python. Which scope the function is from being important is quintessentially Python being Python.

The major gains in Python come from... not using Python. Essentially you have to rewrite your code around the fact that numpy and pandas are the ones really doing the work behind the curtain (e.g. aggressively vectorize, use algorithms that can use vectorization well rather than "normal" ones). Number 8 of the list hints at that.

Re: Performance hacks for faster Python code

#25

(2) surprised me a little. Not because of the performance consequences, but because I almost never see explicit calls to `copy()` in Python (and I read a lot of Python). I think maybe a more realistic example there would be people using splatting without realizing/internalizing that it performs a full copy, e.g. xs = [1, *ys] Another one that stood out was (3). Slots are great, but >95% of the time I'd expect people…

I didn't find 2 surprising either, but I'm a little surprised you never see it. If you want to treat the args to a function as immutable, what can you do besides copy, modify, and return a new object?

> what can you do besides copy, modify, and return a new object?

You can directly produce a modified copy, rather than using a mutating operation to implement the modifications.

It should be noted that "return a modified copy" algorithms can be much more efficient than "mutate the existing data" ones. For example, consider the case of removing multiple elements from a list, specified by a predicate. The version of this code that treats the input as immutable, producing a modified copy, can perform a single pass:

  def without(source, predicate):
      return [e for e in source if not predicate(e)]
whereas mutating code can easily end up with quadratic runtime — and also be difficult to get right:

  def remove_which(source, predicate):
      i = 0
      while i 

Re: Performance hacks for faster Python code

#26

There's some genuinely interesting tips in here, but #10 is for sure just padding so they could call the article "10 Hacks" haha. Everything else is at least somewhat Python specific, but "Hack 10: Avoid repeated function calls in loops" is just applicable to anything.

Yeah, 10 felt like it was written by ai.

A lot of it felt that way, to me.

Re: Performance hacks for faster Python code

#27
post #18

Earlier quoted context omitted.

It's kinda funny how uv is written in Rust and many Python libraries where performance is expected to matter (NumPy, Pandas, PyTorch, re, etc.) are implemented in C. Even if you call into fast code from Python you still have to contend with the GIL which I find very limiting for anything resembling performance.

Python's strong native story has always been one of its biggest draws: people find it ironic that so much of the Python ecosystem is native code, but it plays to Python's strength (native code where performance matters, Python for developer joy/ergonomics/velocity). > Even if you call into fast code from Python you still have to contend with the GIL which I find very limiting for anything resembling performance. It d…

Python is the ultimate (for now) glue language. I'd much rather write a Python script to glue together a CLI utility & a C library with a remote database than try to do that all in C or Rust or BASH.

Re: Performance hacks for faster Python code

#28
post #15
post #7

Some helpful guidelines, but it's 2025 and people still use time.time and no stats with their benchmarks :( In general I feel like these kind of benchmarks might change for each python version, so some caveats might apply.

Perhaps you could suggest what should be used instead of time.time

https://switowski.com/blog/how-to-benchmark-python-code/ has a decent overview of some benchmarking libraries

Re: Performance hacks for faster Python code

#29
post #18
post #2

Maybe also knowing when not to use python, or finding a solution in python that uses C/rust/etc underneath.

It's kinda funny how uv is written in Rust and many Python libraries where performance is expected to matter (NumPy, Pandas, PyTorch, re, etc.) are implemented in C. Even if you call into fast code from Python you still have to contend with the GIL which I find very limiting for anything resembling performance.

In my analysis, the lion's share of uv's performance improvement over pip is not due to being written in Rust. Pip just has horrible internal architecture that can't be readily fixed because of all the legacy cruft.

And for numerical stuff it's absolutely possible to completely trash performance by naively assuming that C/Rust/Fortran etc. will magically improve everything. I saw an example in a talk once where it superficially seemed obvious that the Rust code would implement a much more efficient (IIRC) binary search (at any rate, some sub-linear algorithm on an array), but making the data available to Rust; as a native Rust data structure, required O(N) serialization work.

Re: Performance hacks for faster Python code

#30
post #23

I'm sure this is plenty useful for less experienced people, but the "smart" hacks read a bit like: Hack 1: Don't Use The Obviously Wrong Data Structure For Your Problem! Hack 2: Don't Have The Computer Do Useless Stuff! Hack 3: Don't Allocate Memory When You Don't Need To! And now, a word from our sponsor: AI! Use AI to help AI build AI with AI, now with 15% more AI! Only with AI! Ask your doctor if AI is right for y…

“Hacks” 4-10 could easily be replaced with “use numpy.” Performance gains from doing math better in pure Python are minimal compared with numpy. It’s not unusual for the numpy version of something to end up taking 0.01x as long to run.
Post reply on HN