Skip to content

[pull] master from ruby:master#844

Merged
pull[bot] merged 5 commits intoturkdevops:masterfrom
ruby:master
Mar 12, 2026
Merged

[pull] master from ruby:master#844
pull[bot] merged 5 commits intoturkdevops:masterfrom
ruby:master

Conversation

@pull
Copy link

@pull pull bot commented Mar 12, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

Edouard-chin and others added 5 commits March 12, 2026 08:25
…ference:

- ### Problem

  A gem that has a self-reference in its dependencies would previously
  get a warning during `gem build`, saying it's "discouradged".
  A gem that includes a self-reference can't be updated due to bundler
  filtering it out.

  https://github.com/ruby/rubygems/blob/6fd37f4afeb3943cf508d1394fcf4338a1266f2e/bundler/lib/bundler/resolver.rb#L405-L410

  I think we should be more strict and prevent the gem from building.

  ### Solution

  Raise an explicit error.

  This codepath is only hit when running `gem build`, so this change
  won't affect existing consumers of those gems (it was previously
  possible to install those gems, but not update them, see
  ruby/rubygems#9346 for more context).

ruby/rubygems@fa4673953a
- ### Problem

  Bundler awaits for the dependencies of a gem to be download and installed
  before it proceeds to downloading and installing the dependency itself.
  This creates a bottleneck at the end of the installation process and
  block a thread unnecessarily.

  ### Details

  The installation strategy in Bundler is to await for "leaf gems" to
  be download/installed before the "root gem" is processed.

  For instance, in this scenario:

  - Gem "foo" has a dependency on "bar" (We can call this the "root gem")
  - Gem "bar" has no dependency (We call cal this the "leaf gems")
  - A Gemfile adds "gem 'foo'"

  In this case, only a single thread will have work to do, that is
  because Bundler will queue the gem "bar" to be downloaded and
  installed, and only when "bar" is finished, then Bundler will queue
  work for "foo".

  For **pure ruby gems**, this strategy is a waste of time because
  during the installation, a gem's code is not evaluated and no
  "require" statement is evaluated.

  For gems with native extensions, this strategy make sense. When the
  `extconf.rb` of a gem is evaluated, it's possible that the extconf
  requires a dependency and therefore Bundler needs to wait for those
  dependencies to be installed before it can execute the extconf.
  A typical example is a native extension that require 'mini_portile2'.

  ### Solution

  From the explanation above, I'd like to split the download from
  the installation of a gem.

  The tricky aspect is that there is no RubyGems API to know whether
  a gem has a native extension. The only way to know is after we
  download the gem and read the `metadata` from the tarball.

  So the solution in this patch is as follow:

  1. We download all gems without doing any checks.
  2. Once the gems are downloaded, we now know whether a gem has a
     native extensions.
  3. If a gem is a pure ruby gems, we install it without waiting.
  4. If a gem has a native extension, we check whether its dependencies
     are installed. If a dependency is not yet installed, we put back
     the gem in the queue. It will be dequeued later on and we'll redo
     this logic.

  ### Performance gain

  The speed gain highly depends on how deep the dependency tree is.
  E.g. bar depends on foo which depends on baz which depends on jane ...
  Previously we'd proceed to installing gems just one by one and only
  a single thread would be used.

  In a freshly generated Rails application, the speed gain is not that
  important. And the reason is because we are having a "tail latency"
  issue. Around the end of the installation process, the remaining
  gems to be installed are the one with native extensions, since we
  had to wait for for their dependencies to be installed. Compiling
  them is the slowest part, and since we are doing it at the end then
  the speed gain is not that noticeable.

  ### Misc

  Another advantage of this change is to be able to more easily
  implement this kind of feature ruby/rubygems#9138
  to let users solely download gems, without installing them .

ruby/rubygems@e5e8c0a507
- There are failing tests on Ruby 3.2 due to an expecation that
  checks wheter stderr is empty. In this case, stderr outputs a
  warning from Ruby "warning: loading in progress, circular require
  considered harmful", but this is not true.

  This is a bug in Ruby 3.2 that I also encountered in ruby/rubygems#9100 (comment)
  The problem is that Ruby 3.2 wrongly output this warning when
  multiple threads try to require a file at the same time.
  See https://bugs.ruby-lang.org/issues/19415 which was fixed in Ruby
  3.2.2.

  I opted to add a Mutex, as otherwise users on Ruby 3.2 will have this
  warning output.

ruby/rubygems@713dd5c0e1
@pull pull bot locked and limited conversation to collaborators Mar 12, 2026
@pull pull bot added the ⤵️ pull label Mar 12, 2026
@pull pull bot merged commit 174b54c into turkdevops:master Mar 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants