๐ Experimental Rust frontend for Homebrew/brew (deprecated)
Rust
5
296 commits
updated Jun 8, 2026
brew-rs was an experiment in replacing parts of Homebrew's Ruby frontend with
Rust. It aimed to make common Homebrew commands significantly faster while
preserving Ruby-compatible output and behaviour.
The experiment was abandoned. Local benchmarks showed that Rust was faster for narrow, API-backed bottle fetch batches, especially when archive data was already cached. That did not translate into a better Homebrew install path. When installs included the full Homebrew work of pouring bottles, linking files, writing metadata, running health checks and preserving existing semantics, Ruby was faster on representative fully native comparisons.
The Rust frontend was also only meaningful when it avoided delegation entirely. Delegating back to Ruby added handoff cost and did not answer whether a fully Rust implementation could outperform a fully Ruby implementation. Once delegated paths were excluded, the strongest Rust result was bottle fetching, not installing.
This repository now serves as a record of the Rust frontend experiment and the benchmark work that ended it. The Rust code can still be useful for comparison, but it is no longer considered a shipping direction for Homebrew performance work.
The performance focus moved back to Ruby. The high-level goal became to improve
brew install by reducing the time before useful network or disk I/O begins,
using API-backed bottle metadata earlier and reducing overhead in simple bottle
fetch paths without duplicating Homebrew's install semantics in another
frontend.
Representative zero-delegation benchmarks in a staged local Homebrew prefix showed this split:
| Operation | Ruby | Rust | Result |
|---|---|---|---|
| Fetch 100 bottles, archive cold | 13.07s | 11.42s | Rust 1.14x faster |
| Fetch 100 bottles, archive warm | 1.513s | 0.379s | Rust 3.99x faster |
| Fetch 6 bottles, archive cold | 2.274s | 1.471s | Rust 1.55x faster |
| Fetch 6 bottles, archive warm | 0.842s | 0.313s | Rust 2.69x faster |
| Install 50 simple bottles, archive warm | 8.87s | 93.54s | Ruby 10.5x faster |
| Install 50 simple bottles, archive cold | 75.71s | 132.27s | Ruby 1.75x faster |
| Install 6 bottles, archive cold | 5.287s | 7.632s | Ruby 1.44x faster |
| Install 6 bottles, archive warm | 1.924s | 6.009s | Ruby 3.12x faster |
The useful conclusion was not that Rust could never beat Ruby at individual
operations. It could. The conclusion was that the operations where Rust won were
too narrow to justify a separate frontend, while the operations users most care
about for brew install remained faster in Ruby.
Warm-cache reinstall-style benchmarks were treated as synthetic. They mostly measured repeating work after bottles and metadata were already local, rather than the more common path where Homebrew resolved metadata, downloaded missing bottles, poured kegs, linked files, wrote tabs and handled postinstall work.
Benchmarks based on a separate content-addressed store were also not treated as
evidence that Homebrew could be made faster by swapping frontends. They measured
a different system: one that could skip Homebrew's Cellar layout, tabs, links,
caveats, postinstall semantics, cask behaviour, source fallback, tap logic and
auditability. That can make a demo look quick, but it does not show a faster
brew install unless it preserves the compatibility work users expect from
Homebrew.
The comparison that mattered was fully Ruby versus fully Rust, zero delegation, with cold archive I/O included.
The Rust work informed several ideas for improving the Ruby frontend directly:
Start useful I/O earlier in brew install.
brew prof install FORMULA to separate startup, require,
formula resolution and download enqueue costs.hyperfine --warmup 0 in archive-cold and archive-warm modes,
removing the target brew --cache --formula FORMULA paths before cold
runs.Library/Homebrew/cmd/install.rb, formula_installer.rb,
fetch.rb and download_queue.rb as the main flow to shorten before
touching pour/link correctness.Use API-backed bottle metadata before full Formula inflation where possible.
FormulaStruct use for simple homebrew/core bottles so Ruby
can decide bottle URLs, tags and SHA256 values without building every full
formula object up front.Formula objects for dependency resolution, requirements,
postinstall, caveats, tabs and non-trivial formula logic.brew fetch FORMULA... and the fetch phase of brew install FORMULA... for 1, 10, 50 and 100 formula batches.Formulary.factory, args.named.to_formulae_and_casks and
repeated bottle tag simulation dominate simple bottle fetches.Make immutable bottle cache checks cheaper.
CurlDownloadStrategy#resolve_url_basename_time_file_size,
Utils::Curl.curl_headers,
AbstractFileDownloadStrategy#cached_location and checksum verification.Pathname.glob cache discovery and curl header probes
on warm-cache brew fetch runs.download_strategy behaviour for non-bottle URLs,
source fallback, mirrors, content-disposition filenames, partial downloads
and cask-specific handling.Use brew update to improve Ruby startup and load performance.
brew install and brew fetch load
graph after update work that already changes Homebrew's Ruby files.brew update with and without warmed
Bootsnap caches using hyperfine --warmup 0.brew prof --stackprof install FORMULA to check whether require/load
cost actually moved, rather than only hiding it behind a warm shell.Add first-class phase timing around real install work.
brew prof output instead of relying on
wall-time tables alone.๐ Experimental Rust frontend for Homebrew/brew (deprecated)
Rust
5
296 commits
updated Jun 8, 2026
brew-rs was an experiment in replacing parts of Homebrew's Ruby frontend with
Rust. It aimed to make common Homebrew commands significantly faster while
preserving Ruby-compatible output and behaviour.
The experiment was abandoned. Local benchmarks showed that Rust was faster for narrow, API-backed bottle fetch batches, especially when archive data was already cached. That did not translate into a better Homebrew install path. When installs included the full Homebrew work of pouring bottles, linking files, writing metadata, running health checks and preserving existing semantics, Ruby was faster on representative fully native comparisons.
The Rust frontend was also only meaningful when it avoided delegation entirely. Delegating back to Ruby added handoff cost and did not answer whether a fully Rust implementation could outperform a fully Ruby implementation. Once delegated paths were excluded, the strongest Rust result was bottle fetching, not installing.
This repository now serves as a record of the Rust frontend experiment and the benchmark work that ended it. The Rust code can still be useful for comparison, but it is no longer considered a shipping direction for Homebrew performance work.
The performance focus moved back to Ruby. The high-level goal became to improve
brew install by reducing the time before useful network or disk I/O begins,
using API-backed bottle metadata earlier and reducing overhead in simple bottle
fetch paths without duplicating Homebrew's install semantics in another
frontend.
Representative zero-delegation benchmarks in a staged local Homebrew prefix showed this split:
| Operation | Ruby | Rust | Result |
|---|---|---|---|
| Fetch 100 bottles, archive cold | 13.07s | 11.42s | Rust 1.14x faster |
| Fetch 100 bottles, archive warm | 1.513s | 0.379s | Rust 3.99x faster |
| Fetch 6 bottles, archive cold | 2.274s | 1.471s | Rust 1.55x faster |
| Fetch 6 bottles, archive warm | 0.842s | 0.313s | Rust 2.69x faster |
| Install 50 simple bottles, archive warm | 8.87s | 93.54s | Ruby 10.5x faster |
| Install 50 simple bottles, archive cold | 75.71s | 132.27s | Ruby 1.75x faster |
| Install 6 bottles, archive cold | 5.287s | 7.632s | Ruby 1.44x faster |
| Install 6 bottles, archive warm | 1.924s | 6.009s | Ruby 3.12x faster |
The useful conclusion was not that Rust could never beat Ruby at individual
operations. It could. The conclusion was that the operations where Rust won were
too narrow to justify a separate frontend, while the operations users most care
about for brew install remained faster in Ruby.
Warm-cache reinstall-style benchmarks were treated as synthetic. They mostly measured repeating work after bottles and metadata were already local, rather than the more common path where Homebrew resolved metadata, downloaded missing bottles, poured kegs, linked files, wrote tabs and handled postinstall work.
Benchmarks based on a separate content-addressed store were also not treated as
evidence that Homebrew could be made faster by swapping frontends. They measured
a different system: one that could skip Homebrew's Cellar layout, tabs, links,
caveats, postinstall semantics, cask behaviour, source fallback, tap logic and
auditability. That can make a demo look quick, but it does not show a faster
brew install unless it preserves the compatibility work users expect from
Homebrew.
The comparison that mattered was fully Ruby versus fully Rust, zero delegation, with cold archive I/O included.
The Rust work informed several ideas for improving the Ruby frontend directly:
Start useful I/O earlier in brew install.
brew prof install FORMULA to separate startup, require,
formula resolution and download enqueue costs.hyperfine --warmup 0 in archive-cold and archive-warm modes,
removing the target brew --cache --formula FORMULA paths before cold
runs.Library/Homebrew/cmd/install.rb, formula_installer.rb,
fetch.rb and download_queue.rb as the main flow to shorten before
touching pour/link correctness.Use API-backed bottle metadata before full Formula inflation where possible.
FormulaStruct use for simple homebrew/core bottles so Ruby
can decide bottle URLs, tags and SHA256 values without building every full
formula object up front.Formula objects for dependency resolution, requirements,
postinstall, caveats, tabs and non-trivial formula logic.brew fetch FORMULA... and the fetch phase of brew install FORMULA... for 1, 10, 50 and 100 formula batches.Formulary.factory, args.named.to_formulae_and_casks and
repeated bottle tag simulation dominate simple bottle fetches.Make immutable bottle cache checks cheaper.
CurlDownloadStrategy#resolve_url_basename_time_file_size,
Utils::Curl.curl_headers,
AbstractFileDownloadStrategy#cached_location and checksum verification.Pathname.glob cache discovery and curl header probes
on warm-cache brew fetch runs.download_strategy behaviour for non-bottle URLs,
source fallback, mirrors, content-disposition filenames, partial downloads
and cask-specific handling.Use brew update to improve Ruby startup and load performance.
brew install and brew fetch load
graph after update work that already changes Homebrew's Ruby files.brew update with and without warmed
Bootsnap caches using hyperfine --warmup 0.brew prof --stackprof install FORMULA to check whether require/load
cost actually moved, rather than only hiding it behind a warm shell.Add first-class phase timing around real install work.
brew prof output instead of relying on
wall-time tables alone.