TL;DR
A Ruby developer revisited why uv is much faster than many package managers and examined which of uv’s design choices could be applied to Bundler. Key opportunities include decoupling downloads from installation, increasing parallelism, and avoiding unnecessary runtime evaluation of metadata.
What happened
At a RailsWorld conversation the author was prompted to ask whether Bundler could reach the installation speed of uv. That led to further investigation and a presentation at XO Ruby Portland comparing uv’s performance techniques with Bundler and RubyGems. The analysis draws on Andrew Nesbitt’s post “How uv got so fast,” highlighting that Rust as a language isn’t the only reason for uv’s speed; design and architecture choices matter more. The write-up notes RubyGems already ships dependency metadata (a YAML gemspec in each gem archive) and exposes dependency info via an API, so Bundler doesn’t need to execute package code to learn dependencies. The biggest actionable gap identified is Bundler’s current coupling of gem download and install, plus a queuing model that prevents broader parallelism across dependency chains. The author demonstrates this with a slow test gem server and timing comparisons, and suggests splitting installation into separate stages (details of the proposed four-part split are not present in the source).
Why it matters
- Faster installs reduce developer wait times and speed up CI workflows.
- Architectural changes (not just language choice) can yield large performance gains.
- Decoupling download from install could allow safe parallelism while preserving dependency-order requirements.
- Understanding which constraints are defensive (e.g., upper version bounds) can cut resolver work.
Key facts
- The question originated from a conversation at RailsWorld and was developed into a presentation at XO Ruby Portland.
- The author references Andrew Nesbitt’s post “How uv got so fast” as a primary comparison point.
- RubyGems packages include a YAML gemspec inside the gem archive that declares dependencies, so evaluation of package code is not required to learn dependencies.
- RubyGems.org provides an API that exposes dependency metadata without downloading gem archives.
- uv’s speed is attributed to design decisions beyond its Rust implementation; language choice alone does not explain performance.
- uv ignores upper bounds on 'requires-python' in many cases to reduce resolver backtracking (as noted from Nesbitt’s post).
- Bundler currently couples fetching a gem with installing it, which blocks parallel download while installing other gems.
- A queuing system in Bundler only allows parallel installs for sibling gems, preventing parallelism across dependency chains (example chain a -> b -> c).
- Timed experiments with a slow gem server (3s response per gem) showed chained dependencies took ~11.8 seconds, while three independent gems took ~4.14 seconds in a comparable run.
- Native extensions complicate parallel installs because extconf.rb may require dependencies at build time.
What to watch next
- Whether Bundler maintainers will adopt a design that decouples downloading from installation — not confirmed in the source.
- Any concrete plan to relax dependency-order rules for pure Ruby gems to enable more parallel installs — not confirmed in the source.
- Discussion or decision about a Rust rewrite of Bundler as a route to performance improvements — not confirmed in the source.
Quick glossary
- Bundler: A Ruby dependency manager that resolves and installs gems declared in a Gemfile.
- uv: A fast package installer referenced in the source as an example of high-performance design; noted for being implemented in Rust.
- RubyGems: The package format and hosting ecosystem for distributing Ruby libraries (gems).
- Native extension: Code bundled with a gem that must be compiled or executed during installation, potentially requiring other gems to be present first.
- Resolver: The component that determines which package versions satisfy dependency constraints.
Reader FAQ
Is Bundler inherently slower because it’s written in Ruby?
The source argues that language choice alone doesn’t explain uv’s speed; architectural choices matter more.
Can Bundler download multiple gems in parallel?
Bundler can download sibling gems in parallel today, but its current design couples fetch and install and prevents broader parallelism; changes would be needed to expand parallel downloads.
Would rewriting Bundler in Rust guarantee similar speedups to uv?
Not confirmed in the source; the author suggests that fixing architectural bottlenecks should be the first priority and that a rewrite is not by itself a silver bullet.
What about gems that build native extensions?
Native extensions may require dependencies to be installed before building, which constrains how installations can be reordered or parallelized.
Can Bundler Be as Fast as uv? Posted 3 days ago At RailsWorld earlier this year, I got nerd sniped by someone. They asked “why can’t Bundler be as fast…
Sources
- Can Bundler Be as Fast as Uv?
- Can Bundler Be as Fast as uv? | Lobsters
- Can Bundler Be as Fast as uv?
- How uv got so fast
Related posts
- Python performance and memory numbers every programmer should know
- OpenWorkers: Run Cloudflare Workers-compatible JavaScript on your servers
- Single-Page Apps and the mystery of unexpectedly shallow sessions