Install and compile gems in parallel#1674
Conversation
Currently the gem support code runs a single `gem install` to install the gems in the hook. Dependencies are resolved by the `gem` command, which installs each dependency in sequence. Any gems with native code are compiled, with the compilation stage of each gem using only a single compile task. With this change, gems are installed in parallel (both top-level and dependencies), and any gems with native code allow these gems to use multiple compiler tasks (so using multiple cores where available). (Note that running multiple compilers will be the default `gem` behaviour in Ruby 4, so this ought to be safe). The benefits of this will vary according to computer and hook, but an approximately 3x speed increase has been observed with the rubocop hook (from 38s down to 12s).
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1674 +/- ##
==========================================
+ Coverage 90.35% 91.57% +1.21%
==========================================
Files 96 96
Lines 18661 18842 +181
==========================================
+ Hits 16861 17254 +393
+ Misses 1800 1588 -212 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
📦 Cargo Bloat ComparisonBinary size change: +0.42% (23.8 MiB → 23.9 MiB) Expand for cargo-bloat outputHead Branch ResultsBase Branch Results |
There was a problem hiding this comment.
Pull request overview
This pull request adds parallel gem installation support for Ruby hooks, significantly improving installation performance (approximately 3x speedup observed). The implementation uses a two-phase approach: first resolving dependencies with gem install --explain, then installing each gem in parallel with --ignore-dependencies, with a fallback to sequential installation if the parallel approach fails.
Changes:
- Implemented parallel gem installation using
gem install --explainfor dependency resolution followed by concurrent installation - Added
MAKEFLAGS=-j<CONCURRENCY>to parallelize native extension compilation - Added comprehensive unit tests for the gem name/version/platform parsing logic and integration tests for multiple gemspecs and mixed prebuilt/compiled gems
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/prek/src/languages/ruby/gem.rs | Core implementation of parallel gem installation with dependency resolution, individual gem installation, parsing logic, and fallback to sequential installation |
| crates/prek/tests/languages/ruby.rs | Added integration tests for multiple gemspecs with shared dependencies and mixed prebuilt/compiled gems |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Currently the gem support code runs a single
gem installto install the gems in the hook. Dependencies are resolved by thegemcommand, which installs each dependency in sequence. Any gems with native code are compiled, with the compilation stage of each gem using only a single compile task.With this change, gems are installed in parallel (both top-level and dependencies), and any gems with native code allow these gems to use multiple compiler tasks (so using multiple cores where available). (Note that running multiple compilers will be the default
gembehaviour in Ruby 4, so this ought to be safe).The benefits of this will vary according to computer and hook, but an approximately 3x speed increase has been observed with the rubocop hook (from 38s down to 12s).
Additional speedup for #43