Repository navigation
Upgrade to Rutie 0.13.1, require Ruby 3.2 to 3.4, and release 0.5.0 - #187
Merged
danielpclark merged 10 commits intoOct 7, 2026
Merged
Conversation
Rutie 0.13 is the Ruby 3.2, 3.3 and 3.4 line and drops Ruby 2, so the gem's Ruby requirement moves with it, as does the CI matrix (Linux and Windows on each of the three, macOS on 3.4) and the release tarballs. The extension's own code compiles unchanged. What Ruby 3 changed around the extension: * thermite reads GitHub release feeds with REXML, which Ruby 3 no longer loads without a gem, so the gem now depends on rexml. * rubocop 0.53 can't load its configuration on Ruby 3 (Psych 4 changed `safe_load`), so the development dependency moves to rubocop 1.x with rubocop-performance for the Performance cops the configuration enables. The configuration keeps the same cops under their current names; the Rails cops, which never applied to this gem, are dropped. * The ruby/spec and mspec submodules move from their 2021 commits to the ruby/spec suite for Ruby 3.2.9 and the mspec it was run with, the last suite tested against 3.2, 3.3 and 3.4 together. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
Ruby 3.1 gave `File.dirname` a second argument, the number of trailing components to remove, and the monkeypatch and refinement only took one, so the ruby/spec specs for it errored with "wrong number of arguments" once the suite moved to Ruby 3.2. `FasterPath.dirname` now takes the level too: it is converted like Ruby's `NUM2INT` (`to_int`, a negative level is an `ArgumentError`), and the dirname is taken that many times, stopping at the root like Ruby does. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
The move from Ruby 2.5 to 2.7 to Ruby 3.2 to 3.4 drops every Ruby the 0.4 line supported, so this is a new minor version. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
Ruby 3's `Pathname#absolute?` is a single regexp match, not the `chop_basename` loop of Ruby 2, so the Rust version is a smaller improvement over it (about 25% on Ruby 3.4, 45% on 3.3) and the old 80% floors failed. These are provisional floors so `rake test` passes; the next commit re-measures every method on Ruby 3. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
The benchmark timed all five rounds of Ruby's implementation, then all five of FasterPath's, and compared the averages, so anything else the machine did during one of the two phases landed on one side only. For the cheapest methods that was the whole result: `absolute?` on Ruby 3.4 measured anywhere between -12% and 66% from one run to the next. The rounds now alternate between the two implementations, and each is measured by its best round, which shows the code rather than the interruptions; three runs in a row now agree within a few points. The suite's string literals are frozen too. The `absolute?`, `relative?` and `directory?` benchmarks compared frozen `Pathname` constants with literals allocated on every call to FasterPath, two allocations the monkeypatch (which passes `@path`) never makes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
Changed Files
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
`File.dirname("", 0)` is "." in Ruby, as with any level, where the new
level support returned the empty path unchanged. The test that compared
the two passed locally only because it ran with the monkeypatches on,
comparing FasterPath with itself; it now checks fixed expectations taken
from Ruby 3.3, so it means the same with and without them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
The README tables now show Ruby 3.4.6 and 3.2.9 (the median of 3 runs of `LONG_RUN=10 rake pbench`, measured by the best of interleaved rounds), in place of the Ruby 2.7 and 2.5 figures, which stay in the Rutie 0.10 section as history. The floors follow the documented rule again: about half of the lower of the two figures, rounded down to a multiple of 5, with the filesystem-bound methods kept at 0 and the _compat methods without one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
danielpclark
marked this pull request as ready for review
October 7, 2026 05:13
`rake pbench --long-run` fails with "invalid option: --long-run" before the Rakefile sees ARGV, so the branch that set LONG_RUN from it could never run. LONG_RUN itself, which the README documents, is the way to run longer benchmarks. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
The README tables now have a column for each supported Ruby, measured with `LONG_RUN=30` (5 rounds of 300,000 calls per method, three times the previous depth) on a dedicated CPU core, three runs each; the runs agree within a few points except for the filesystem-bound methods. The floors are about half of each method's lowest figure across the three. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rutie 0.13 is the Ruby 3.2, 3.3 and 3.4 line and drops Ruby 2, so this moves the gem from Ruby 2.5–2.7 to Ruby 3.2–3.4 and bumps it to 0.5.0. The extension's own Rust code compiles against 0.13.1 unchanged; everything else here is what Ruby 3 changed around it.
Commits
Cargo.toml, the gemspec'srequired_ruby_version, the CI matrix (Linux and Windows on 3.2/3.3/3.4, macOS on 3.4) and the release tarballs. Three things Ruby 3 broke: thermite needs REXML (a bundled gem since 3.0) so the gem now depends onrexml; rubocop 0.53 can't load its config on Ruby 3 (Psych 4) so the dev dependency moves to rubocop 1.x with rubocop-performance, keeping the same cops under their current names and dropping the never-applicable Rails ones; and the ruby/spec and mspec submodules move from 2021 to the ruby/spec suite for Ruby 3.2.9 (the last tested against 3.2, 3.3 and 3.4 together).File.dirname(plus theFile.dirname("", 0)fix). Ruby 3.1 addedFile.dirname(path, level); the monkeypatch and refinement only took one argument, so the ruby/spec specs errored.FasterPath.dirnametakes the level now, converted like Ruby'sNUM2INT.absolute?on 3.4 measured between -12% and 66% from run to run. Rounds now alternate and each side is measured by its best round. The suite's string literals are also frozen, since three benchmarks compared frozenPathnameconstants with literals allocated on every call to FasterPath.--long-runflag that rake rejected before the Rakefile could see it;LONG_RUNis the documented way.LONG_RUN=30(5 rounds of 300,000 calls per method), three runs each on a dedicated CPU core; the runs agree within a few points except for the filesystem-bound methods. The floors are about half of each method's lowest figure. The Ruby 2.7/2.5 figures stay in the Rutie 0.10 section as history.The cheapest methods shave off less than they did on Ruby 2,
absolute?above all (56% on 3.4, 53% on 3.3, 43% on 3.2, versus 96% on Ruby 2): Ruby 3's ownPathname#absolute?is a single regexp match where Ruby 2's walked the path withchop_basename, so there is less left to win. Everything else is within a few points of the Ruby 2 figures.Verification
With Rutie 0.13.1 on Linux x86_64:
TEST_MONKEYPATCHES=true WITH_REGRESSION=true ENCODING=true bundle exec rake test(cargo, minitest, rubocop, pbench, mspec) passes on Ruby 3.2.9, 3.3.6 and 3.4.6. The ruby/spec run coverscore/file/basename,core/file/extname,core/file/dirnameandlibrary/pathnameat the 3.2.9 suite commit. CI on this PR is green on all 19 jobs: Linux 3.2/3.3/3.4, Windows 3.2/3.3/3.4 (the MSVC build against RubyInstaller works out of the box) and macOS 3.4.Follow-up: #188 (stacked on this) switches to thermite 0.14 (danielpclark/thermite#2) once that is published. Rutie 0.14.1 is also out; this PR stays on 0.13.1 as asked.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CXvfgWzuq28ewqT3AyhX4Z