Skip to content

Upgrade to Rutie 0.13.1, require Ruby 3.2 to 3.4, and release 0.5.0 - #187

Merged
danielpclark merged 10 commits into
masterfrom
claude/determined-shannon-ybz9nf-rutie-0.13
Oct 7, 2026
Merged

danielpclark merged 10 commits into
masterfrom
claude/determined-shannon-ybz9nf-rutie-0.13

Conversation

@danielpclark

@danielpclark danielpclark commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

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

  • Upgrade to Rutie 0.13.1 and require Ruby 3.2 to 3.4. Cargo.toml, the gemspec's required_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 on rexml; 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).
  • Support the level argument of File.dirname (plus the File.dirname("", 0) fix). Ruby 3.1 added File.dirname(path, level); the monkeypatch and refinement only took one argument, so the ruby/spec specs errored. FasterPath.dirname takes the level now, converted like Ruby's NUM2INT.
  • Bump the gem to 0.5.0.
  • Measure pbench by the best of interleaved rounds. The harness timed all five rounds of one implementation then all five of the other, and compared averages, so anything else the machine did landed on one side: 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 frozen Pathname constants with literals allocated on every call to FasterPath.
  • Drop the --long-run flag that rake rejected before the Rakefile could see it; LONG_RUN is the documented way.
  • Benchmark Ruby 3.4, 3.3 and 3.2 for the 0.5.0 tables. The README has a column per supported Ruby, from 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 own Pathname#absolute? is a single regexp match where Ruby 2's walked the path with chop_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 covers core/file/basename, core/file/extname, core/file/dirname and library/pathname at 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

danielpclark and others added 5 commits October 7, 2026 04:44
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
@semanticdiff-com

semanticdiff-com Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  .github/workflows/ci.yml  53% smaller
  src/pathname.rs  5% smaller
  .rubocop.yml  2% smaller
  Cargo.lock Unsupported file format
  Cargo.toml Unsupported file format
  README.md Unsupported file format
  Rakefile Unsupported file format
  faster_path.gemspec Unsupported file format
  lib/faster_path/optional/monkeypatches.rb Unsupported file format
  lib/faster_path/optional/refinements.rb Unsupported file format
  lib/faster_path/version.rb Unsupported file format
  spec/mspec  0% smaller
  spec/ruby_spec  0% smaller
  test/dirname_test.rb Unsupported file format
  test/pbench/pbench.rb Unsupported file format
  test/pbench/pbench_suite.rb Unsupported file format
  test/refinements/dirname_test.rb Unsupported file format

danielpclark and others added 3 commits October 7, 2026 05:01
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 and others added 2 commits October 7, 2026 05:29
`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
@danielpclark
danielpclark merged commit f0e3789 into master Oct 7, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant