Live data from Hacker News

How uv got so fast

nesbitt.io

221–230 of 468 posts

Re: How uv got so fast

#221

The most surprising part of uv's success to me isn't Rust at all, it's how much speed we "unlocked" just by finally treating Python packaging as a well-specified systems problem instead of a pile of historical accidents. If uv had been written in Go or even highly optimized CPython, but with the same design decisions (PEP 517/518/621/658 focus, HTTP range tricks, aggressive wheel-first strategy, ignoring obviously de…

It's not just greenfield-ness but the fact it's a commercial endeavor (even if the code is open-source). Building a commercial product means you pay money (or something they equally value) to people to do your bidding. You don't have to worry about politics, licensing, and all the usual FOSS-related drama. You pay them to set their opinions aside and build what you want, not what they want (and if that doesn't work,…

That doesn't make any sense. You can do open source by yourself and not accept any input.

How's the company behind uv making money?

Re: How uv got so fast

#222
post #218

Earlier quoted context omitted.

> No, every code path you don't execute is that. Even in compiled languages, binaries have to get loaded into memory. For Python it's much worse. On my machine: $ time python -c 'pass' real 0m0.019s user 0m0.013s sys 0m0.006s $ time pip --version > /dev/null real 0m0.202s user 0m0.182s sys 0m0.021s Almost all of that extra time is either the module import process or garbage collection at the end. Even with cached byt…

> binaries have to get loaded into memory. Unless memory mapped by the OS with no impact on runtime for unused parts? > imports related to Requests are deferred Exactly, so again have no impact?

> Unless memory mapped by the OS with no impact on runtime for unused parts?

Yeah, this is presumably why a no-op `uv` invocation on my system takes ~50 ms the first time and ~10 ms each other time.

> Exactly, so again have no impact?

Only if your invocation of pip manages to avoid an Internet request. Note: pip will make an Internet request if you try to install a package by symbolic name even if it already has the version it wants in cache, because its cache is an HTTP cache rather than a proper download cache.

But even then, there will be hundreds of imports mainly related to Rich and its dependencies.

Re: How uv got so fast

#223
post #75
post #4

> PEP 658 went live on PyPI in May 2023. uv launched in February 2024. The timing isn’t coincidental. uv could be fast because the ecosystem finally had the infrastructure to support it. A tool like uv couldn’t have shipped in 2020. The standards weren’t there yet. How/why did the package maintainers start using all these improvements? Some of them sound like a bunch of work, and getting a package ecosystem to move i…

> If setup.py was working okay for folks, what incentivized them to start using pyproject.toml? It wasn't working okay for many people, and many others haven't started using pyproject.toml. For what I consider the most egregious example: Requests is one of the most popular libraries, under the PSF's official umbrella, which uses only Python code and thus doesn't even need to be "built" in a meaningful sense. It has a…

I should have mentioned one of the main reasons setup.py turns out not okay for people (aside from the general unpleasantness of running code to determine what should be, and mostly is, static metadata): in the legacy approach, Setuptools has to get `import`ed from the `setup.py` code before it can run, but running that code is the way to find out the dependencies. Including build-time dependencies. Specifically Setuptools itself. Good luck if the user's installed version is incompatible with what you've written.

Re: How uv got so fast

#224
post #218

Earlier quoted context omitted.

> binaries have to get loaded into memory. Unless memory mapped by the OS with no impact on runtime for unused parts? > imports related to Requests are deferred Exactly, so again have no impact?

> Unless memory mapped by the OS with no impact on runtime for unused parts? Yeah, this is presumably why a no-op `uv` invocation on my system takes ~50 ms the first time and ~10 ms each other time. > Exactly, so again have no impact? Only if your invocation of pip manages to avoid an Internet request. Note: pip will make an Internet request if you try to install a package by symbolic name even if it already has the…

> Only if your invocation of pip manages to avoid an Internet request.

Yes it does, by definition, the topic of discussion is the impact of unused code paths? How is http cache relevant here? That's a used path!

Re: How uv got so fast

#225
post #208

Earlier quoted context omitted.

I can't find the quote for this, but I remember Python maintainers wanted package installing and management to be separate things. uv did the opposite, and instead it's more like npm.

Do you remember the reason? I spend most of my time in the Java and JS ecosystems where one tool does both jobs. In my mind they’re pretty heavily linked. But that may be based on not experiencing the opposite. At least not as far as I can remember.

Separation of concerns. They just wanted pip to be a good installer and let package managers* use pip. But uv didn't end up doing that either.

* or workflow tools as they're called here https://packaging.python.org/en/latest/guides/tool-recommend...

Re: How uv got so fast

#226

Earlier quoted context omitted.

I'm my experience this is definitely where rust shined. The language wasn't really what made the project succeed so much as having relatively curious, meticulous, detail-oriented people on hand who were interested in solving hard problems. Sometimes I thought our teams would be a terrible fit for more cookie-cutter applications where rapid development and deployment was the primary objective. We got into the weeds al…

Rust is also a systems language. I am still wrapping my mind around why it is so popular for so many end projects when its main use case and goals were basically writing a browser a maybe OS drivers. But that’s precisely why it is good for developer tools. And it turns out people who write systems code are really damn good at writing tools code. As someone who cut my teeth on C and low level systems stuff I really ou…

I mean, you can always replace Python with LuaJIT or Perl... or Nim... or Crystal... or Odin... or with Rust....

Re: How uv got so fast

#228
post #42

I remain baffled about these posts getting excited about uv’s speed. I’d like to see a real poll but I personally can’t imagine people listing speed as one of the their top ten concerns about python package managers. What are the common use cases where the delay due to package installation is at all material? Edit to add: I use python daily

conda can take an hour to tell you your desired packages are unsatisifiable saying that, other than the solver, most of what uv does is always going to be IO bound

People criticising conda's solver prove they haven't used it in years.

Re: How uv got so fast

#229

The most surprising part of uv's success to me isn't Rust at all, it's how much speed we "unlocked" just by finally treating Python packaging as a well-specified systems problem instead of a pile of historical accidents. If uv had been written in Go or even highly optimized CPython, but with the same design decisions (PEP 517/518/621/658 focus, HTTP range tricks, aggressive wheel-first strategy, ignoring obviously de…

> it's how much speed we "unlocked" just by finally treating Python packaging as a well-specified systems problem instead of a pile of historical accidents.

A lot of that, in turn, boils down to realizing that it could be fast, and then expecting that and caring enough about it.

> but with the same design decisions (PEP 517/518/621/658 focus, HTTP range tricks, aggressive wheel-first strategy, ignoring obviously defensive upper bounds, etc.), I strongly suspect we'd be debating a 1.3× vs 1.5× speedup instead of a 10× headline

I'm doing a project of this sort (although I'm hoping not to reinvent the wheel (heh) for the actual resolution algorithm). I fully expect that some things will be barely improved or even slower, but many things will be nearly as fast as with uv.

For example, installing from cache (the focus for the first round) mainly relies on tools in the standard library that are written in C and have to make system calls and interact with the filesystem; Rust can't do a whole lot to improve on that. On the other hand, a new project can improve by storing unpacked files in the cache (like uv) instead of just the artifact (I'm storing both; pip stores the artifact, but with a msgpack header) and hard-linking them instead of copying them (so that the system calls do less I/O). It can also improve by actually making the cached data accessible without a network call (pip's cache is an HTTP cache; contacting PyPI tells it what the original download URL is for the file it downloaded, which is then hashed to determine its path).

For another example, pre-compiling bytecode can be parallelized; there's even already code in the standard library for it. Pip hasn't been taking advantage of that all this time, but to my understanding it will soon feature its own logic (like uv does) to assign files to compile to worker processes. But Rust can't really help with the actual logic being parallelized, because that, too, is written purely in C (at least for CPython), within the interpreter.

> why did it take a greenfield project to give Python the package manager behavior people clearly wanted for the last decade?

(Zeroth, pip has been doing HTTP range tricks, or at least trying, for quite a while. And the exact point of PEP 658 is to obsolete them. It just doesn't really work for sdists with the current level of metadata expressive power, as in other PEPs like 440 and 508. Which is why we have more PEPs in the pipeline trying to fix that, like 725. And discussions and summaries like https://pypackaging-native.github.io/.)

First, you have to write the standards. People in the community expect interoperability. PEP 518 exists specifically so that people could start working on alternatives to Setuptools as a build backend, and PEP 517 exists so that such alternatives could have the option of providing just the build backend functionality. (But the people making things like Poetry and Hatch had grander ideas anyway.)

But also, consider the alternative: the only other viable way would have been for pip to totally rip apart established code paths and possibly break compatibility. And, well, if you used and talked about Python at any point between 2006 and 2020, you should have the first-hand experience required to complete that thought.

Specifically regarding the "aggressive wheel-first strategy", I strongly encourage you to read the discussion on https://github.com/pypa/pip/issues/9140.

Re: How uv got so fast

#230
post #220
post #171

Earlier quoted context omitted.

I wonder how much Rust's default to statically link almost everything helped here? That should make deployment of uv even easier?

I don't think this makes a meaningful difference. The installation is a `curl | sh`, which downloads a tarball, which gets extracted to some directory in $PATH. It currently includes two executables, but having it contain two executables and a bunch of .so libraries would be a fairly trivial change. It only gets messy when you want it to make use of system-provided versions of the libraries, rather than simply vendor…

It gets mess not just in that way but also someone can have a weird LD_LIBRARY_PATH that starts to have problems. Statically linking drastically simplifies distribution and you’ve had to have distributed 0 software to end users to believe otherwise. The only platform this isn’t the case for is Apple because they natively supported app bundles. I don’t know if flat pack solves the distribution problem because I’ve not seen a whole lot of it in the ecosystem - most people seem to generally still rely on the system package manager and commercial entities don’t seem to really target flat pack.
Post reply on HN