ruby/lib/bundler/resolver/strategy.rb
Hartley McGuire 752a1d7854 [rubygems/rubygems] Implement pub_grub strategy interface
My application spends more than 30% of time during `bundle update`
comparing versions due to versions being sorted inside
next_package_to_try. This has been addressed in pub_grub by defining a
strategy interface (a `#next_package_and_version` method) which allows
consumers to have finer control over the heuristic to select the next
package to try.

This commit implements the new strategy interface to remove extraneous
version sorting (previously in next_package_to_try) since only the final
count of versions is used.

Combined with a previous change to pub_grub (already applied to
Bundler), this commit results in `bundle update` taking only half the
time it did on 2.6.5.

62f69e27f0
2025-03-27 13:57:26 +09:00

40 lines
1 KiB
Ruby

# frozen_string_literal: true
module Bundler
class Resolver
class Strategy
def initialize(source)
@source = source
end
def next_package_and_version(unsatisfied)
package, range = next_term_to_try_from(unsatisfied)
[package, most_preferred_version_of(package, range).first]
end
private
def next_term_to_try_from(unsatisfied)
unsatisfied.min_by do |package, range|
matching_versions = @source.versions_for(package, range)
higher_versions = @source.versions_for(package, range.upper_invert)
[matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
end
end
def most_preferred_version_of(package, range)
versions = @source.versions_for(package, range)
# Conditional avoids (among other things) calling
# sort_versions_by_preferred with the root package
if versions.size > 1
@source.sort_versions_by_preferred(package, versions)
else
versions
end
end
end
end
end