# brew-rs **Repository Path**: Homebrew2/brew-rs ## Basic Information - **Project Name**: brew-rs - **Description**: No description available - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-10 - **Last Updated**: 2026-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🦀 brew-rs (Rust frontend experiment for Homebrew) `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. ## Current Status 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. ## Benchmark Summary 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. ## Potential Ruby Performance Improvements The Rust work informed several ideas for improving the Ruby frontend directly: - Start useful I/O earlier in `brew install`. - Focus on the time between process start and the first bottle manifest or bottle archive transfer, not only total command time. - Use `brew prof install FORMULA` to separate startup, require, formula resolution and download enqueue costs. - Compare with `hyperfine --warmup 0` in archive-cold and archive-warm modes, removing the target `brew --cache --formula FORMULA` paths before cold runs. - Treat `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. - Investigate `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. - Keep full `Formula` objects for dependency resolution, requirements, postinstall, caveats, tabs and non-trivial formula logic. - Compare `brew fetch FORMULA...` and the fetch phase of `brew install FORMULA...` for 1, 10, 50 and 100 formula batches. - Check whether `Formulary.factory`, `args.named.to_formulae_and_casks` and repeated bottle tag simulation dominate simple bottle fetches. - Make immutable bottle cache checks cheaper. - GHCR bottle blobs with API-provided SHA256 metadata should not need the same freshness path as arbitrary URLs, mirrors, casks, source tarballs and VCS strategies. - Profile `CurlDownloadStrategy#resolve_url_basename_time_file_size`, `Utils::Curl.curl_headers`, `AbstractFileDownloadStrategy#cached_location` and checksum verification. - Measure the cost of `Pathname.glob` cache discovery and curl header probes on warm-cache `brew fetch` runs. - Preserve current generic `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. - Prewarm stable Bootsnap caches for the `brew install` and `brew fetch` load graph after update work that already changes Homebrew's Ruby files. - Avoid cache keys that churn on every checkout path, timestamp or vendor state change. - Compare the first command after `brew update` with and without warmed Bootsnap caches using `hyperfine --warmup 0`. - Use `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. - Track planning, API metadata load, full formula inflation, dependency resolution, download enqueue, curl headers, curl body, checksum, symlink, extraction, pour, link, tab writing, cleanup and postinstall. - Keep timings opt-in and machine-readable enough to compare repeated runs. - Use the phase data to interpret `brew prof` output instead of relying on wall-time tables alone. - Make cold-cache tests explicit: metadata cold, archive cold, archive warm and fully warm are different workloads.