[HN Gopher] How uv got so fast
___________________________________________________________________
How uv got so fast
Author : zdw
Score : 370 points
Date : 2025-12-26 17:13 UTC (5 hours ago)
(HTM) web link (nesbitt.io)
(TXT) w3m dump (nesbitt.io)
| yjftsjthsd-h wrote:
| > No bytecode compilation by default. pip compiles .py files to
| .pyc during installation. uv skips this step, shaving time off
| every install. You can opt in if you want it.
|
| Are we losing out on performance of the actual installed thing,
| then? (I'm not 100% clear on .pyc files TBH; I'm _guessing_ they
| speed up start time?)
| woodruffw wrote:
| No, because Python itself will generate bytecode for packages
| once you actually import them. uv just defers that to first-
| import time, but the cost is amortized in any setting where
| imports are performed over multiple executions.
| yjftsjthsd-h wrote:
| That sounds like yes? Instead of doing it once at install
| time, it's done once at first use. It's only once so it's not
| _persistently_ slower, but that is a perf hit.
|
| My first cynical instinct is to say that this is uv making
| itself look better by deferring the costs to the application,
| but it's probably a good trade-off if any significant
| percentage of the files being compiled might not be used ever
| so the overall cost is lower if you defer to run time.
| woodruffw wrote:
| > It's only once so it's not persistently slower, but that
| is a perf hit.
|
| Sure, but you pay that hit either way. Real-world
| performance is always usage based: the assumption that uv
| makes is that people run (i.e. import) packages more often
| than they install them, so amortizing at the point of the
| import machinery is better for the mean user.
|
| (This assumption is not universal, naturally!)
| dddgghhbbfblk wrote:
| Ummm, your comment is backwards, right?
| woodruffw wrote:
| 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.)
| beacon294 wrote:
| Probably for any case where an actual human is doing it. On
| an image you obviously want to do it at bake time, so I
| feel default off with a flag would have been a better
| design decision for pip.
|
| I just read the thread and use Python, I can't comment on
| the % speedup attributed to uv that comes from this
| optimization.
| Epa095 wrote:
| Images are a good example where doing it at install-time
| is probably the best yeah, since every run of the image
| starts 'fresh', losing the compilation which happened
| last time the image got started.
|
| If it was a optional toggle it would probably become best
| practice to activate compilation in dockerfiles.
| saidnooneever wrote:
| you are right. it depends on how often this first start is,
| if its bad or not..most usecases id guess (total guess,
| have limited exp with python projects professionally) its
| not an issue.
| tedivm wrote:
| You can change it to compile the bytecode on install with a
| simple environment variable (which you should do when
| building docker containers if you want to sacrifice some
| disk space to decrease initial startup time for your app).
| VorpalWay wrote:
| I think they are making the bet that most modules won't be
| imported. For example if I install scipy, numpy, Pillow or
| such: what are the chances that I use a subset of the
| modules vs literally all of them?
|
| I would bet on a subset for pretty much any non-trivial
| package (i.e. larger than one or two user facing modules).
| And for those trivial packages? Well they are usually
| small, so the cost is small as well. I'm sure there are
| exceptions: maybe a single gargantuan module thst consists
| of autogenerated FFI bindings for some C library or such,
| but that is likely the minority.
| salviati wrote:
| Historically the practice of producing pyc files on install
| started with system wide installed packages, I believe, when
| the user running the program might lack privileges to write
| them. If the installer can write the .oy files it can also
| write the .pyc, while the user running them might not in that
| location.
| plorkyeran wrote:
| If you have a dependency graph large enough for this to be
| relevant, it almost certainly includes a large number of files
| which are never actually imported. At worst the hit to startup
| time will be equal to the install time saved, and in most cases
| it'll be a lot smaller.
| hauntsaninja wrote:
| Yes, uv skipping this step is a one time significant hit to
| start up time. E.g. if you're building a Dockerfile I'd
| recommend setting `--compile-bytecode` / `UV_COMPILE_BYTECODE`
| thundergolfer wrote:
| This optimization hits serverless Python the worst. At Modal we
| ensure users of uv are setting UV_COMPILE_BYTECODE to avoid the
| cold start penalty. For large projects .pyc compilation can
| take hundreds of milliseconds.
| zahlman wrote:
| > I'm not 100% clear on .pyc files TBH; I'm guessing they speed
| up start time?
|
| They do.
|
| > Are we losing out on performance of the actual installed
| thing, then?
|
| When you consciously precompile Python source files, you can
| parallelize that process. When you `import` from a `.py` file,
| you only get that benefit if you somehow coincidentally were
| already set up for `multiprocessing` and happened to have your
| workers trying to `import` different files at the same time.
| blintz wrote:
| > 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 is hard. Was there motivation
| to speed up installs across the ecosystem? If setup.py was
| working okay for folks, what incentivized them to start using
| pyproject.toml?
| yjftsjthsd-h wrote:
| Because static declaration was clearly safer and more
| performant? My question is why pip isn't fully taking advantage
| eesmith wrote:
| Because pip contains decades of built-up code and lacks the
| people willing to work on updating it.
| zahlman wrote:
| > 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
| pyproject.toml file as of the last release. But that file _isn
| 't specifying the build setup_ following PEP 517/518/621
| standards. That's supposed to appear in the next minor release,
| but they've only done patch releases this year and the relevant
| code is not at the head of the repo, _even though it already
| caused problems for them this year_. It 's been more than a
| year and a half since the last minor release.
| woodruffw wrote:
| I think this post does a really good job of covering how multi-
| pronged performance is: it certainly doesn't hurt uv to be
| written in Rust, but it benefits _immensely_ from a decade of
| thoughtful standardization efforts in Python that lifted the
| ecosystem away from needing `setup.py` on the hot path for most
| packages.
| yjftsjthsd-h wrote:
| I think a lot of rust rewrites have this benefit; if you start
| with hindsight you can do better more easily. Of course, rust
| is also _often_ beneficial for its own sake, so it 's a one-two
| punch:)
| woodruffw wrote:
| Completely agreed!
| pxc wrote:
| Succinctly, perhaps with some loss of detail:
|
| "Rewrite" is important as "Rust".
| pixelpoet wrote:
| as important as
| s_ting765 wrote:
| Rust rewrites are known for breaking (compatibility with)
| working software. That's all there is to them.
| pxc wrote:
| 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-established) standards in the Python community
| that don't share this insanity!
| s_ting765 wrote:
| My gripe is with Rust rewrites. Not uv. Though I very
| much think uv is overhyped.
| eduction wrote:
| 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 also implies that python also prefers toml
| and wheel metadata, but has to shell out to parse those,
| unlike uv.
| Lammy wrote:
| I would say the downside of them is that they're known for
| replacing GPL software with MIT software
| Levitating wrote:
| > I think a lot of rust rewrites have this benefit
|
| I think Rust itself has this benefit
| glaslong wrote:
| 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.
| steve_adams_86 wrote:
| 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
| all the time (sometimes because of rust itself), but it
| happened to be important to do so.
|
| Had we built those projects with JavaScript or Python I
| suspect the outcomes would have been worse for reasons apart
| from the language choice.
| zahlman wrote:
| > having relatively curious, meticulous, detail-oriented
| people on hand who were interested in solving hard
| problems.... Had we built those projects with JavaScript or
| Python I suspect the outcomes would have been worse for
| reasons apart from the language choice.
|
| I genuinely can't understand why you suppose that has to do
| with the implementation language at all.
| KPGv2 wrote:
| > I genuinely can't understand why you suppose that has
| to do with the implementation language at all.
|
| Languages that attract novice programmers (JS is an
| obvious one; PHP was one 20 years ago) have a higher
| noise to signal ratio than one that attracts intermediate
| and above programmers.
|
| If you grabbed an average Assembly programmer today, and
| an average JavaScript programmer today, who do you think
| is more careful about programming? The one who needs to
| learn arcane shit to do basic things and then has to
| compile it in order to test it out, or the one who can
| open up Chrome's console and console.log("i love
| boobies")
|
| How many embedded systems programmers suck vs full stack
| devs? I'm not saying full stack devs are inferior. I'm
| saying that more inferior coders are attracted to the
| latter because the barriers to entry are SO much easier
| to bypass.
| Calavar wrote:
| Paul Graham said the same thing about Python 20 years ago
| [1], and back then it was true. But once a programming
| langauge hits mainstream, this ceases to be a good filter.
|
| [1] https://paulgraham.com/pypar.html
| jghn wrote:
| This is important. The benefit here isn't the language
| itself. It's the fact that you're pulling from an esoteric
| language. People should not overfit and feel that whichever
| language is achieving that effect today is special in this
| regard.
| bri3d wrote:
| 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 language-nerd side quest thrown in, but
| overall, a good selection metric. I do think it's one of the
| best Rewrite it in X languages available today due to the
| availability of good developers with Rewrite in Rust project
| experience.
|
| The Haskell commentary is curious to me. I've used Haskell
| professionally but never tried to hire for it. With that
| said, the other FP-heavy languages that were popular
| ~2010-2015 were absolutely horrible for this in my
| experience. I generally subscribe to a vague notion that
| "skill in a more esoteric programming language will usually
| indicate a combination of ability to learn/plasticity and
| interest in the trade," however, using this concept, I had
| really bad experiences hiring both Scala and Clojure
| engineers; there was _way_ too much academic interest in
| language concepts and way too little practical interest in
| doing work. YMMV :)
| mannycalavera42 wrote:
| Clojure engineers not interested in doing work? That's
| surprising
| nurettin wrote:
| > When a package says it requires python<4.0, uv ignores the
| upper bound and only checks the lower.
|
| I will bring popcorn on python 4 release date.
| yjftsjthsd-h wrote:
| If it's really not doing any upper bound checks, I could see it
| blowing up under more mundane conditions; Python includes
| breaking changes on .x releases, so I've had eg. packages
| _require_ (say) Python 3.10 when 3.11 /12 was current.
| dev_l1x_be wrote:
| I always bring popcorn on major version changes for any
| programming language. I hope Rust's never 2.0 stance holds.
| zahlman wrote:
| It would be popcorn-worthy regardless, given the rhetoric
| surrounding the idea in the community.
| ethin wrote:
| > 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.
| nemothekid wrote:
| Given the context of the article, I think "Rust specific" here
| means that "it couldn't be done in python".
|
| For example "No interpreter startup" is not specific to Rust
| either.
| kbd wrote:
| It's Rust vs Python in this case.
| woodruffw wrote:
| I think the framing in the post is that it's specific to Rust,
| relative to what Python packaging tools are otherwise written
| in (Python). It's not very easy to do zero-copy deserialization
| in pure Python, from experience.
|
| (But also, I think Rust can fairly claim that it's made zero-
| copy deserialization a lot easier and safer.)
| stefan_ wrote:
| I suppose it can fairly claim that now every other library
| and blog post invokes "zero-copy" this and that, even in the
| most nonsensical scenarios. It's a technique for when you can
| literally not afford the memory bandwidth, because you are
| trying to saturate a 100Gbps NIC or handling 8k 60Hz video,
| not for compromising your data serialization schemes
| portability for marketing purposes while all applications hit
| the network first, disk second and memory bandwidth never.
| woodruffw wrote:
| Many of the hot paths in uv involve an entirely locally
| cached set of distributions that need to be loaded into
| memory, very lightly touched/filtered, and then sunk to
| disk somewhere else. In those contexts, there are
| measurable benefits to not transforming your
| representation.
|
| (I'm agnostic on whether zero-copy "matters" in every
| single context. If there's no complexity cost, which is
| what Rust's abstractions often provide, then it doesn't
| really hurt.)
| vlovich123 wrote:
| You've got this backward. The vast majority of time due to
| spatial and temporal locality, in practice for any
| application you're actually usually doing CPU registers
| first, cache second, memory third, disk fourth, network
| cache fifth, and network origin sixth. So this stuff does
| actually matter for performance.
|
| Also, aside from memory bandwidth, there's a latency cost
| inherent in traversing object graphs - 0 copy techniques
| ensure you traverse that graph minimally, just what's
| needed to actually be accessed which is huge when you scale
| up. There's a difference between one network request and
| fetching 1 MB vs making 100 requests to fetch 10kib and
| this difference also appears in memory access patterns
| unless they're absorbed by your cache (not guaranteed for
| object graph traversal that a package manager would be
| doing).
| zahlman wrote:
| The point is that the packaging tool can analyze files from
| within the archives it downloads, without writing them to
| disk.
| zahlman wrote:
| I can't even imagine what "safety" issue you have in mind.
| Given that "zero-copy" apparently means "in-memory" (a
| deserialized version of the data necessarily cannot be the
| same object as the original data), that's not even difficult
| to do with the Python standard library. For example,
| `zipfile.ZipFile` has a convenience method to write to file,
| but writing to in-memory data is as easy as
| with zipfile.ZipFile(archive_name) as a: with
| a.open(file_name) as f, io.BytesIO() as b:
| b.write(f.read()) return b.getvalue()
|
| (That does, of course, copy data around _within memory_ ,
| but.)
| woodruffw wrote:
| > Given that "zero-copy" apparently means "in-memory" (a
| deserialized version of the data necessarily cannot be the
| same object as the original data), that's not even
| difficult to do with the Python standard library
|
| This is not what zero-copy means. Here's a working
| definition[1].
|
| Specifically, it's not just about keeping things in memory;
| copying in memory is normal. The goal is to _not_ make
| copies (or more precisely, what Rust would call "clones"),
| but to instead convey the original representation/views of
| that representation through the program's lifecycle where
| feasible.
|
| > a deserialized version of the data necessarily cannot be
| the same object as the original data
|
| rust-asn1 would be an example of a Rust library that
| doesn't make any copies of data unless you explicitly ask
| it to. When you load e.g. a Utf8String[2] in rust-asn1, you
| get a view into the original input buffer, not an
| intermediate owning object created from that buffer.
|
| > (That does, of course, copy data around within memory,
| but.)
|
| Yes, that's what makes it not zero-copy.
|
| [1]: https://rkyv.org/zero-copy-deserialization.html
|
| [2]:
| https://docs.rs/asn1/latest/asn1/struct.Utf8String.html
| landr0id wrote:
| 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.
| agumonkey wrote:
| very nice article, always good to get a review of what a "simple"
| looking tool does behind the scense
|
| about rust though
|
| some say a nicer language helps finding the right architecture
| (heard that about cpp veteran dropping it for ocaml, any
| attempted idea would take weeks in cpp, was a few days in ocaml,
| they could explore more)
|
| also the parallelism might be a benefit the language orientation
|
| enough semi fanboyism
| aswegs8 wrote:
| uv seems to be a pet peeve of HN. I always thought pipenv was
| good but yeah, seems like I was being ignorant
| aw1621107 wrote:
| > uv seems to be a pet peeve of HN.
|
| Unless I've been seeing very different submissions than you,
| "pet peeve" seems like the exact opposite of what is actually
| the case?
| VerifiedReports wrote:
| Indeed; I don't think he knows what "peeve" means...
| glaucon wrote:
| I too use pipenv unless there's a reason not to. I hope people
| use whatever works best for them.
|
| I feel that sometimes there's a desire on the part of those who
| use tool X that everyone should use tool X. For some types of
| technology (car seat belts, antibiotics...) that might be
| reasonable but otherwise it seems more like a desire for
| validation of the advocate's own choice.
| epage wrote:
| > uv is fast because of what it doesn't do, not because of what
| language it's written in. The standards work of PEP 518, 517,
| 621, and 658 made fast package management possible. Dropping
| eggs, pip.conf, and permissive parsing made it achievable. Rust
| makes it a bit faster still.
|
| Isn't assigning out what all made things fast presumptive without
| benchmarks? Yes, I imagine a lot is gained by the work of those
| PEPs. I'm more questioning how much weight is put on dropping of
| compatibility compared to the other items. There is also no
| coverage for decisions influenced by language choice which likely
| influences "Optimizations that don't need Rust".
|
| This also doesn't cover subtle things. Unsure if rkyv is being
| used to reduce the number of times that TOML is parsed but TOML
| parse times do show up in benchmarks in Cargo and Cargo/uv's TOML
| parser is much faster than Python's (note: Cargo team member,
| `toml` maintainer). I wish the TOML comparison page was still up
| and showed actual numbers to be able to point to.
| zahlman wrote:
| > Isn't assigning out what all made things fast presumptive
| without benchmarks?
|
| We also have the benchmark of "pip now vs. pip years ago". That
| has to be controlled for pip version and Python version, but
| the former hasn't seen a lot of changes that are relevant for
| most cases, as far as I can tell.
|
| > This also doesn't cover subtle things. Unsure if rkyv is
| being used to reduce the number of times that TOML is parsed
| but TOML parse times do show up in benchmarks in Cargo and
| Cargo/uv's TOML parser is much faster than Python's (note:
| Cargo team member, `toml` maintainer). I wish the TOML
| comparison page was still up and showed actual numbers to be
| able to point to.
|
| This is interesting in that I wouldn't expect that the typical
| resolution involves a particularly large _quantity_ of TOML. A
| package installer really only needs to look at it at all when
| building from source, and part of what these standards have
| done for us is improve wheel coverage. (Other relevant PEPs
| here include 600 and its predecessors.) Although that has also
| largely been driven by education within the community, things
| like e.g. https://blog.ganssle.io/articles/2021/10/setup-py-
| deprecated... and https://pradyunsg.me/blog/2022/12/31/wheels-
| are-faster-pure-... .
| pecheny wrote:
| The content is nice and insightful! But God I wish people stopped
| using LLMs to 'improve' their prose... Ironically, some day we
| might employ LLMs to re-humanize texts that had been already
| massacred.
| laidoffamazon wrote:
| Interestingly I didn't catch this, I liked it for not looking
| LLM written!
| yunohn wrote:
| "Why this matters" being the final section is a guaranteed
| give away, among innumerable others.
| rick_dalton wrote:
| I realized once I was in the "optimizations that dont need
| rust" section. Specifically "This is concurrency, not
| language magic."
| yunohn wrote:
| I have reached a point where any AI smell (of which this
| articles has many) makes me want to exit immediately. It feels
| tortuous to my reading sensibilities.
|
| I blame fixed AI system prompts - they forcibly collapse all
| inputs into the same output space. Truly disappointing that
| OpenAI et all have no desire to change this before everything
| on the internet sounds the same forever.
| fleebee wrote:
| You're probably right about the latter point, but I do wonder
| how hard it'd be to mask the default "marketing copywriter"
| tone of the LLM by asking it to assume some other tone in
| your prompt.
|
| As you said, reading this stuff is taxing. What's more, this
| is a daily occurrence by now. If there's a silver lining,
| it's that the LLM smells are so obvious at the moment; I can
| close the tab as soon as I notice one.
| SatvikBeri wrote:
| > do wonder how hard it'd be to mask the default "marketing
| copywriter" tone of the LLM by asking it to assume some
| other tone in your prompt.
|
| Fairly easy, in my wife's experience. She repeatedly got
| accused of using chatgpt in her original writing (she's not
| a native english speaker, and was taught to use many of the
| same idioms that LLMs use) until she started actually using
| chatgpt with about two pages of instructions for tone to
| "humanize" her writing. The irony is staggering.
| mattkevan wrote:
| It's pretty easy. I've written a fairly detailed guide to
| help Claude write in my tone of voice. It also coaxes it to
| avoid the obvious AI tells such as 'It's not X it's Y'
| sentences, American English and overuse of emojis and em
| dashes.
|
| It's really useful for taking my first drafts and cleaning
| them up ready for a final polish.
| efilife wrote:
| I also don't read AI slop. It's disrespectful to any reader.
| captn3m0 wrote:
| The author' blog was on HN a few days ago as well for an
| article on SBOMs and Lockfiles. They've done a lot of work in
| the supply-chain security side and are clearly knowledgeable,
| and yet the blog post got similarly "fuzzified" by the LLM.
| ec109685 wrote:
| The article info is great, but why do people put up with LLM
| ticks and slop in their writing? These sentences add no value and
| treats the reader as stupid.
|
| > This is concurrency, not language magic.
|
| > This is filesystem ops, not language-dependent.
|
| Duh, you literally told me that the previous sentence and 50
| million other times.
| aurumque wrote:
| This kind of writing goes deeper than LLM's, and reflects a
| decline in both reading ability, patience, and attention.
| Without passing judgement, there are just more people now who
| benefit from repetition and summarization embedded directly in
| the article. The reader isn't 'stupid', just burdened.
| twoodfin wrote:
| Indeed, I am coming around in the past few weeks to
| realization and acceptance that the LLM editorial voice is a
| benefit to an order of magnitude more hn readers than those
| (like us) for whom it is ice pick in the nostril stuff.
|
| Oh well, all I can do is flag.
| hallvard wrote:
| Great post, but the blatant chatgpt-esque feel hits hard... Don't
| get me wrong, I love astral! and the content, but...
| hallvard wrote:
| Reading the other replies here makes it really obvious that
| this is some LLM's writing. Maybe even all of it...
| skywhopper wrote:
| This is great to read because it validates my impression that
| Python packaging has always been a tremendous overengineered
| mess. Glad to see someone finally realized you just need a simple
| standard metadata file per package.
| looneysquash wrote:
| 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?
| stevemk14ebr wrote:
| What are you talking about, this all exists
| VerifiedReports wrote:
| So... will uv make Python a viable cross-platform utility
| solution?
|
| I was going to learn Python for just that (file-conversion
| utilities and the like), but everybody was so down on the messy
| ecosystem that I never bothered.
| zahlman wrote:
| It has been viable for a long time, and the kinds of projects
| you describe are likely well served by the standard library.
| pseudosavant wrote:
| I write all of my scripts in Python with PEP 723 metadata and
| run them with `uv run`. Works great on Windows and Linux for
| me.
| IshKebab wrote:
| Yes, uv basically solves the terrible Python tooling situation.
|
| In my view that was by far the biggest issue with Python - a
| complete deal-breaker really. But uv solves it pretty well.
|
| The remaining big issues are a) performance, and b) the import
| system. uv doesn't do anything about those.
|
| Performance may not be an issue in some cases, and the import
| system is ... tolerable if you're writing "a python project".
| If you're writing some other project and considering using
| Python for its scripting system, e.g. to wrangle multiple build
| systems or whatever than the import mess is a bigger issue and
| I would thing long and hard before picking it over Deno.
| pwdisswordfishy wrote:
| > Some of uv's speed comes from Rust. But not as much as you'd
| think. Several key optimizations could be implemented in pip
| today: [...] Python-free resolution
|
| Umm...
| andy99 wrote:
| 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
| pants2 wrote:
| The biggest benefit is in CI environments and Docker images and
| the like where all packages can get reinstalled on every run.
| gordonhart wrote:
| `poetry install` on my dayjob's monolith took about 2 minutes,
| `uv sync` takes a few seconds. Getting 2 minutes back on every
| CI job adds up to a lot of time saved
| toenail wrote:
| The speed is nice, but I switched because uv supports "pip
| compile" from pip-tools, and it is better at resolving
| dependencies. Also pip-tools uses (used?) internal pip methods
| and breaks frequently because of that, uv doesn't.
| recov wrote:
| Docker builds are a big one, at least at my company. Any tool
| that reduces wait time is worth using, and uv is an amazing
| tool that removes that wait time. I take it you might not use
| python much as it solves almost every pain point, and is fast
| which feels rare.
| stavros wrote:
| I can run `uvx sometool` without fear because I know that it'll
| take a few seconds to create a venv, download all the
| dependencies, and run the tool. uv's speed has literally
| changed how I work with Python.
| quectophoton wrote:
| I wouldn't say without fear, since you're one typo away from
| executing a typo-squatted malicious package.
|
| I do use it on CI/CD pipelines, but I wouldn't dare type uvx
| commands myself on a daily basis.
| stavros wrote:
| uvx isn't more risky than `pip install`, which is what I
| used before.
| rsyring wrote:
| As a multi decade Python user, uv's speed is "life changing".
| It's a huge devx improvement. We lived with what came before,
| but now that I have it, I would never want to go back and it's
| really annoying to work on projects now that aren't using it.
| thraxil wrote:
| Working heavily in Python for the last 20 years, it absolutely
| was a big deal. `pip install` has been a significant percentage
| of the deploy time on pretty much every app I've ever deployed
| and I've spent countless hours setting up various caching
| techniques trying to speed it up.
| SatvikBeri wrote:
| Setting up a new dev instance took 2+ hours with pip at my
| work. Switching to uv dropped the Python portion down to <1
| minute, and the overall setup to 20 minutes.
|
| A similar, but less drastic speedup applied to docker images.
| techbruv wrote:
| At a previous job, I recall updating a dependency via poetry
| would take on the order of ~5-30m. God forbid after 30 minutes
| something didn't resolve and you had to wait another 30 minutes
| to see if the change you made fixed the problem. Was not an
| enjoyable experience.
|
| uv has been a delight to use
| pxc wrote:
| > updating a dependency via poetry would take on the order of
| ~5-30m. God forbid after 30 minutes something didn't resolve
| and you had to wait another 30 minutes to see if the change
| you made fixed the problem
|
| I'd characterize that as unusable, for sure.
| patrick91 wrote:
| for me it's being able to do `uv run whatever` and always know
| I have the correct dependencies
|
| (also switching python version is so fast)
| pseudosavant wrote:
| I avoided Python for years, especially because of package and
| environment management. Python is now my go to for projects
| since discovering uv, PEP 723 metadata, and LLMs' ability to
| write Python.
| adammarples wrote:
| It's annoying. Do you use poetry? Pipenv? It's annoying.
| IshKebab wrote:
| Do you still remain baffled after the many replies that people
| actually do like their tooling to be not dog slow like pip is?
| VorpalWay wrote:
| CI: I changed a pipeline at work from pip and pipx to uv, it
| saved 3 minutes on a 7 minute pipeline. Given how
| oversubscribed our runners are, anything saving time is a big
| help.
|
| It is also really nice when working interactivly to have snappy
| tools that don't take you out of the flow more than absolutely
| more than necessary. But then I'm quite sensitive to this, I'm
| one of those people who turn off all GUI animations because
| they waste my time and make the system feel slow.
| zahlman wrote:
| It's not just about delays being "material"; waiting on the
| order of seconds for a venv creation (and knowing that this is
| because of pip bootstrapping itself, when it _should_ just be
| able to install cross-environment instead of having to wait
| until 2022 for an ugly, limited hack to support that) is
| _annoying_.
|
| But small efficiencies do matter; see e.g.
| https://danluu.com/productivity-velocity/.
| zahlman wrote:
| I've talked about this many times on HN this year but got beaten
| to the punch on blogging it seems. Curses.
|
| ... Okay, after a brief look, there's still lots of room for me
| to comment. In particular:
|
| > pip's slowness isn't a failure of implementation. For years,
| Python packaging required executing code to find out what a
| package needed.
|
| This is largely refuted by the fact that pip is _still_ slow,
| _even when installing from wheels_ (and getting PEP 600 metadata
| for them). Pip is actually still slow even when doing _nothing_.
| (And when you create a venv and allow pip to be bootstrapped in
| it, that bootstrap process takes in the high 90s percent of the
| total time used.)
| didibus wrote:
| There's an interesting psychology at play here as well, if you
| are a programmer that chooses a "fast language" it's indicative
| of your priorities already, it's often not much the language, but
| that the programmer has decided to optimize for performance from
| the get go.
| bastawhiz wrote:
| > When a package says it requires python<4.0, uv ignores the
| upper bound and only checks the lower. This reduces resolver
| backtracking dramatically since upper bounds are almost always
| wrong. Packages declare python<4.0 because they haven't tested on
| Python 4, not because they'll actually break. The constraint is
| defensive, not predictive.
|
| This is kind of fascinating. I've never considered runtime upper
| bound requirements. I can think of compelling reasons for lower
| bounds (dropping version support) or exact runtime version
| requirements (each version works for exact, specific CPython
| versions). But now that I think about it, it seems like upper
| bounds solve a hypothetical problem that you'd never run into in
| practice.
|
| If PSF announced v4 and declared a set of specific changes, I
| think this would be reasonable. In the 2/3 era it was definitely
| reasonable (even necessary). Today though, it doesn't actually
| save you any trouble.
| wging wrote:
| I think the article is being careful not to say uv ignores
| _all_ upper bound checks, but specifically 4.0 upper bound
| checks. If a package says it requires python < 3.0, that's
| still super relevant, and I'd hope for uv to still notice and
| prevent you from trying to import code that won't work on
| python 3. Not sure what it actually does.
| breischl wrote:
| I read the article as saying it ignores all upper-bounds, and
| 4.0 is just an example. I could be wrong though - it seems
| ambiguous to me.
|
| But if we accept that it currently ignores any upper-bounds
| checks greater than v3, that's interesting. Does that imply
| that once Python 4 is available, uv will slow down due to
| needing to actually run those checks?
| VorpalWay wrote:
| Are there any plans to actually make a 4.0 ever? I remember
| hearing a few years ago that after the transition to 3.0,
| the core devs kind of didn't want to repeat that mess ever
| again.
|
| That said, even if it does happen, I highly doubt that is
| the main part of the speed up compared to pip.
| ofek wrote:
| > 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 (Datadog) allowed me and two other
| engineers to improve various aspects of Python packaging for
| nearly an entire quarter. One of the items was to satisfy a few
| long-standing pip feature requests. I discovered that the cross-
| platform resolution feature I considered most important is
| basically incompatible [1] with the current code base.
| Maintainers would have to decide which path they prefer.
|
| [1]: https://github.com/pypa/pip/issues/13111
| zahlman wrote:
| > 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_....)
| eviks wrote:
| > Every code path you don't have is a code path you don't wait
| for.
|
| No, every code path you don't execute is that. Like
|
| > No .egg support.
|
| How does that explain anything if the egg format is obsolete and
| not used?
|
| Similar with spec strictness fallback logic - it's only slow if
| the packages you're installing are malformed, otherwise the logic
| will not run and not slow you down.
|
| And in general, instead of a list of irrelevant and potentially
| relevant things would be great to understand some actual time
| savings per item (at least those that deliver the most speedup)!
|
| But otherwise great and seemingly comprehensive list!
| zahlman wrote:
| > 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 and then garbage collection. Even with cached bytecode,
| the former requires finding and reading from literally hundreds
| of files, deserializing via `marshal.loads` and then running
| top-level code, which includes creating objects to represent
| the functions and classes.
|
| It used to be even worse than this; in recent versions, imports
| related to Requests are deferred to the first time that an
| HTTPS request is needed.
| efilife wrote:
| this shit is ChatGPT-written and I'm really tired of it. If I
| wanted to read chatgpt I would have asked it myself. Half of the
| article are nonsensical repeated buzzwords thrown in for
| absolutely no reason
| IshKebab wrote:
| 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.
| ggm wrote:
| Some of these speed ups looked viable to backport into pip
| including parallel download, delayed .pyc, ignore egg, version
| checks.
|
| Not that I'd bother since uv does venv so well. But, "it's not
| all rust runtime speed" implies pip could be faster too.
| robertclaus wrote:
| At Plotly we did a decent amount of benchmarking to see how much
| the different defaults `uv` uses lead to its performance. This
| was necessary so we could advise our enterprise customers on the
| transition. We found you lost almost all of the speed gains if
| you configured uv behave as much like pip as you could. A trivial
| example is the precompile flag, which can easily be 50% of pips
| install time for a typical data science venv.
|
| https://plotly.com/blog/uv-python-package-manager-quirks/
| zahlman wrote:
| The precompilation thing was brought up to the uv team several
| months ago IIRC. It doesn't make as much of a difference for uv
| as for pip, because when uv is told to pre-compile it can
| parallelize that process. This is easily done in Python (the
| standard library even provides rudimentary support, which
| Python's own Makefile uses); it just isn't in pip yet (I
| understand it will be soon).
| w10-1 wrote:
| I like the implication that we can have an alternative to uv
| speed-wise, but I think reliability and understandability are
| more important in this context (so this comment is a bit off-
| topic).
|
| What I want from a package manager is that it just works.
|
| That's what I mostly like about uv.
|
| Many of the changes that made speed possible were to reduce the
| complexity and thus the likelihood of things not working.
|
| What I don't like about uv (or pip or many other package
| managers), is that the programmer isn't given a clear mental
| model of what's happening and thus how to fix the inevitable
| problems. Better (pubhub) error messages are good, but it's rare
| that they can provide specific fixes. So even if you get 99%
| speed, you end up with 1% perplexity and diagnostic black boxes.
|
| To me the time that matters most is time to fix problems that
| arise.
| zahlman wrote:
| > the programmer isn't given a clear mental model of what's
| happening and thus how to fix the inevitable problems.
|
| This is a priority for PAPER; it's built on a lower-level API
| so that programmers _can_ work within a clear mental model, and
| I will be trying my best to communicate well in error messages.
| pkaodev wrote:
| AI slop
| rvz wrote:
| TLDR: Because Rust.
|
| This entire AI generated article with lots of text just to just
| say the obvious.
| punnerud wrote:
| 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."
___________________________________________________________________
(page generated 2025-12-26 23:00 UTC)