Live data from Hacker News

How uv got so fast

nesbitt.io

121–130 of 468 posts

Re: How uv got so fast

#121
post #11

> Zero-copy deserialization. uv uses rkyv to deserialize cached data without copying it. The data format is the in-memory format. This is a Rust-specific technique. This (zero-copy deserialization) is not a rust-specific technique, so I'm not entirely sure why the author describes it as one. Any good low level language (C/C++ included) can do this from my experience.

They speak about “technique” but rkyv is a Rust-specific format. Could be an editing error or maybe they’re suggesting it’s more difficult in python.

Re: How uv got so fast

#122
post #78

> pip could implement parallel downloads, global caching, and metadata-only resolution tomorrow. It doesn’t, largely because backwards compatibility with fifteen years of edge cases takes precedence. pip is simply difficult to maintain. Backward compatibility concerns surely contribute to that but also there are other factors, like an older project having to satisfy the needs of modern times. For example, my employer…

> pip is simply difficult to maintain. Backward compatibility concerns surely contribute to that but also there are other factors, like an older project having to satisfy the needs of modern times.

Backwards compatibility is the one thing that prevents the code in an older project from being replaced with a better approach in situ. It cannot be more difficult than a rewrite, except that rewrites (arguably including my project) may hold themselves free to skip hard legacy cases, at least initially (they might not be relevant by the time other code is ready).

(I would be interested in hearing from you about UX designs for cross-platform resolution, though. Are you just imagining passing command-line flags that describe the desired target environment? What's the use case exactly — just making a .pylock file? It's hard to imagine cross-platform installation....)

Re: How uv got so fast

#123
post #86

Earlier quoted context omitted.

Someone once told me a benefit of staffing a project for Haskell was it made it easy to select for the types of programmers that went out of their way to become experts in Haskell. Tapping the Rust community is a decent reason to do a project in Rust.

It's an interesting debate. The flip side of this coin is getting hires who are more interested in the language or approach than the problem space and tend to either burn out, actively dislike the work at hand, or create problems that don't exist in order to use the language to solve them. With that said, Rust was a good language for this in my experience. Like any "interesting" thing, there was a moderate bit of lan…

Clojure engineers not interested in doing work? That's surprising

Re: How uv got so fast

#124
My favorite speed up trick: “ HTTP range requests for metadata. Wheel files are zip archives, and zip archives put their file listing at the end. uv tries PEP 658 metadata first, falls back to HTTP range requests for the zip central directory, then full wheel download, then building from source. Each step is slower and riskier. The design makes the fast path cover 99% of cases. None of this requires Rust.”

Re: How uv got so fast

#125
post #65

Earlier quoted context omitted.

Rust rewrites are known for breaking (compatibility with) working software. That's all there is to them.

In Python's case, as the article describes quite clearly, the issue is that the design of "working software" (particularly setup.py) was bad to the point of insane (in much the same way as the NPM characteristics that enabled the recent Shai Hulud supply chain attacks, but even worse). At some point, compatibility with insanity has got to go. Helpfully, though, uv retains compatibility with newer (but still well-esta…

Actually uv retains compatibility with the setup.py “insanity,” according to the article:

> uv parses TOML and wheel metadata natively, only spawning Python when it hits a setup.py-only package that has no other option

The article implies that pip also prefers toml and wheel metadata, but has to shell out to parse those, unlike uv.

Re: How uv got so fast

#126

Mmm I don't buy it. Not many projects use setup.py now anyway and pip is still super slow. > Plenty of tools are written in Rust without being notably fast. This also hasn't been my experience. Most tools written in Rust are notably fast.

> Not many projects use setup.py now anyway and pip is still super slow.

Yes, but that's still largely not because of being written in Python. The architecture is really just that bad. Any run of pip that touches the network will end up importing more than 500 modules and a lot of that code will simply not be used.

For example, one of the major dependencies is Rich, which includes things like a 3600-entry mapping of string names to emoji; Rich in turn depends on Pygments which normally includes a bunch of rules for syntax highlighting in dozens of programming languages (but this year they've finished trimming those parts of the vendored Pygments).

Another thing is that pip's cache is an HTTP cache. It literally doesn't know how to access its own package download cache without hitting the network, and it does that access through wrappers that rely on cachecontrol and Requests.

Re: How uv got so fast

#127

Mmm I don't buy it. Not many projects use setup.py now anyway and pip is still super slow. > Plenty of tools are written in Rust without being notably fast. This also hasn't been my experience. Most tools written in Rust are notably fast.

Mine either. Choosing Rust by no means guarantees your tool will be fast—you can of course still screw it up with poor algorithms. But I think most people who choose Rust do so in part because they aspire for their tool to be "blazing fast". Memory safety is a big factor of course, but if you didn't care about performance, you might have gotten that via a GCed (and likely also interpreted or JITed or at least non-LLVM-backend) language.

Re: How uv got so fast

#128

Earlier quoted context omitted.

Ummm, your comment is backwards, right?

Which part? The assumption is that when you `$TOOL install $PACKAGE`, you run (i.e. import) `$PACKAGE` more than you re-install it. So there's no point in slowing down (relatively less common) installation events when you can pay the cost once on import. (The key part being that 'less common' doesn't mean a non-trivial amount of time.)

Why would you want to slow down the more common thing instead of the less common thing? I'm not following that at all. That's why I asked if that's backwards.

Re: How uv got so fast

#129

I don't have any real disagreement with any of the details the author said. But still, I'm skeptical. If it is doable, the best way to prove it is to actually do it. If no one implements it, was it ever really doable? Even if there is no technical reason, perhaps there is a social one?

I guess you mean doing the things in Python that are supposedly doable from Python.

Yeah, to a zeroth approximation that's my current main project (https://github.com/zahlman/paper). Of course, I'm just some rando with apparently serious issues convincing myself to put in regular unpaid work on it, but I can see in broad strokes how everything is going to work. (I'm not sure I would have thought about, for example, hard-linking files when installing them from cache, without uv existing.)

Re: How uv got so fast

#130
This post is excellent. I really like reading deep dives like this that take a complex system like uv and highlight the unique design decisions that make it work so well.

I also appreciate how much credit this gives the many previous years of Python standards processes that enabled it.

Update: I blogged more about it here, including Python recreations of the HTTP range header trick it uses and the version comparison via u64 integers: https://simonwillison.net/2025/Dec/26/how-uv-got-so-fast/

Post reply on HN