Project

General

Profile

Feature #21532

Updated by Eregon (Benoit Daloze) 1 day ago

There was discussion in #17473 and before to define most of Pathname in Ruby code and not in the C extension. 

 I have made a PR to achieve that: https://github.com/ruby/pathname/pull/57 
 I would like to merge it soon to avoid conflicts. 

 Once upon a time, Pathname was pure-Ruby: https://github.com/ruby/ruby/blob/95bc02237635d3fe42532bfe53038257575cee75/lib/pathname.rb 

 This PR goes back to that, and reuses that original Ruby code, but keeps the C extension implementation of `<=>` and `sub` as those two are significantly faster. 
 The other Pathname methods are actually faster in Ruby than in C, because all these methods just do `rb_funcall()` and `rb_ivar_get()` and those in C code have no inline cache, but the corresponding method calls and `@path` have inline caches in Ruby code. 
 https://railsatscale.com/2023-08-29-ruby-outperforms-c/ is an explanation of that. 

 Therefore having Pathname defined in Ruby seems a clear win for many reasons: 
 * Much clearer implementation, so easier to read what the code does 
 * Easier to maintain 
 * Safer (no risk of accessing out of bounds memory or e.g. passing the wrong number of arguments to `rb_funcall`) 
 * Significantly Actually faster, because of these inline caches (more details in https://github.com/ruby/pathname/pull/57#issue-3234862768): 

 | Speedup (this branch / master) | ruby 3.4.2 | ruby 3.4.2 + YJIT | caches, see the table at the end of https://github.com/ruby/pathname/pull/57#issue-3234862768 
 | --- | --- | --- | 
 | `Pathname.new(".")` | 1.02x | 1.19x | 
 | `Pathname#directory?` | 1.03x | 1.06x | 
 | `Pathname#to_s` | 1.85x | 2.38x | 

 * Better for JITs as they can optimize this, notably `...` vs the C extension being a blackbox 
 * Works on JRuby (which does not support C extensions) 
 * Works on TruffleRuby (some Ruby C API functions that the extension uses are not supported on TruffleRuby)

Back