Skip to content

[pull] master from ruby:master#869

Merged
pull[bot] merged 113 commits intoturkdevops:masterfrom
ruby:master
Mar 20, 2026
Merged

[pull] master from ruby:master#869
pull[bot] merged 113 commits intoturkdevops:masterfrom
ruby:master

Conversation

@pull
Copy link

@pull pull bot commented Mar 20, 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 : )

kddnewton and others added 27 commits March 20, 2026 09:37
Prism changed structure quite a bit. Most of the previously-public
structs are now opaque. This requires quite a bit of changes
internally.

It also triggered some unrelated changes, which were necessary
because Prism's main header used to pull in standard headers. So
box.c and jit.c are now no longer transitively getting all the
headers they needed.
The method for marking something as deprecated is currently unused but seems fine leave as is.

ruby/prism@5b523dfe6e
- ### Problem

  Comparing Gem::Version objects is slow. It's particularly a problem
  because `Gem::Version#<=>` is called million of times during
  resolution when using a real world Gemfile in a large application.

  The comparison has to compare all segments between the two objects,
  enter conditional branches and check lexicographical order when
  version is a prerelease.

  ### Solution

  I'd like to provide a fast path for the simple scenarios by turning
  a version into an integer.
  By "simple scenario" I mean version up to 4 segments which
  represents the vast majority of the version scheme released by
  maintainers.

  For sake of simplicity and understability of the code I opted to not
  include prelease version ("1.0.0.alpha") in the fast path.
  We'd need to turn the "pre" string into a integer while keeping
  lexicographical order (`1.0.0.beta` > `1.0.0.alpha`) and I felt
  it wasn't worth the complexity.

  Overall, this change makes comparing version up to 5x faster (when
  one version is higher than the other)
  There is no speed gain when 2 versions are the same as there is
  already a fast path implemented.

  Checking prerelease version is a bit slower now due to a `nil` check
  we are doing.

  ### Benchmarks

  ```ruby
  require "benchmark/ips"

  a = Gem::Version.new("5.3.1")
  b = Gem::Version.new("5.3.2")
  c = Gem::Version.new("5.3.1")
  d = Gem::Version.new("2.0.0.alpha")

  Benchmark.ips do |x|
    x.report("less than regular:") { a <=> b }
    x.report("less than optimized:") { a <=> b }
    x.hold!("lesser_than_temp_results")
    x.compare!(order: :baseline)
  end

  Benchmark.ips do |x|
    x.report("greater than regular:") { b <=> a }
    x.report("greater than optimized:") { b <=> a }
    x.hold!("greater_than_temp_results")
    x.compare!(order: :baseline)
  end

  Benchmark.ips do |x|
    x.report("equal regular:") { a <=> c }
    x.report("equal optimized:") { a <=> c }
    x.hold!("equal_temp_results")
    x.compare!(order: :baseline)
  end

  Benchmark.ips do |x|
    x.report("prerelase regular:") { a <=> d }
    x.report("prerelease optimized:") { a <=> d }
    x.hold!("prerelease_temp_results")
    x.compare!(order: :baseline)
  end
  ```

  ```
  Warming up --------------------------------------
  less than optimized:     1.352M i/100ms
  Calculating -------------------------------------
  less than optimized:     13.599M (± 0.8%) i/s   (73.53 ns/i) -     68.947M in   5.070279s

  Comparison:
    less than regular::  2622912.7 i/s
    less than optimized:: 13599139.2 i/s - 5.18x  faster

  _________________________

  Warming up --------------------------------------
  greater than optimized:
                         1.355M i/100ms
  Calculating -------------------------------------
  greater than optimized:
                         13.581M (± 0.6%) i/s   (73.63 ns/i) -     69.120M in   5.089497s

  Comparison:
  greater than regular::  2637899.0 i/s
  greater than optimized:: 13581319.7 i/s - 5.15x  faster

  _________________________

  Warming up --------------------------------------
    equal optimized:     1.360M i/100ms
  Calculating -------------------------------------
    equal optimized:     13.577M (± 0.7%) i/s   (73.65 ns/i) -     68.010M in   5.009445s

  Comparison:
    equal regular:: 13885209.5 i/s
    equal optimized:: 13576932.0 i/s - same-ish: difference falls within error

  _________________________

  Warming up --------------------------------------
  prerelease optimized:
                       358.680k i/100ms
  Calculating -------------------------------------
  prerelease optimized:
                       3.595M (± 0.6%) i/s  (278.17 ns/i) -     18.293M in   5.088687s

   Comparison:
     prerelase regular::  4174692.2 i/s
     prerelease optimized::  3594907.8 i/s - 1.16x  slower
  ```

ruby/rubygems@6ef9f279d9
The 4.0.0 version break CI.
@pull pull bot locked and limited conversation to collaborators Mar 20, 2026
@pull pull bot added the ⤵️ pull label Mar 20, 2026
@pull pull bot merged commit 26bedb5 into turkdevops:master Mar 20, 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.

8 participants