Feature #21532
closedDefine most of Pathname in Ruby code
Description
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 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 | 
|---|---|---|
| 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)
        
           Updated by Eregon (Benoit Daloze) 3 months ago
          Updated by Eregon (Benoit Daloze) 3 months ago
          
          
        
        
      
      - Related to Feature #17473: Make Pathname to embedded class of Ruby added
        
           Updated by Eregon (Benoit Daloze) 3 months ago
          Updated by Eregon (Benoit Daloze) 3 months ago
          
          
        
        
      
      - Description updated (diff)
        
           Updated by Eregon (Benoit Daloze) 3 months ago
          Updated by Eregon (Benoit Daloze) 3 months ago
          
          
        
        
      
      - Description updated (diff)
        
           Updated by Eregon (Benoit Daloze) 3 months ago
          Updated by Eregon (Benoit Daloze) 3 months ago
          
          
        
        
      
      - Description updated (diff)
        
           Updated by akr (Akira Tanaka) 2 months ago
          Updated by akr (Akira Tanaka) 2 months ago
          
          
        
        
      
      Ok. Merge it.
        
           Updated by Eregon (Benoit Daloze) 2 months ago
          Updated by Eregon (Benoit Daloze) 2 months ago
          
          
        
        
      
      - Status changed from Open to Closed
Thanks!
        
           Updated by hsbt (Hiroshi SHIBATA) 2 months ago
          
          ยท Edited
          Updated by hsbt (Hiroshi SHIBATA) 2 months ago
          
          ยท Edited
        
        
      
      https://github.com/ruby/pathname/pull/57 is incomplete.
Some methods are incompatibility with C Version and Ruby version of Pathname broke with Windows platform.
        
           Updated by Eregon (Benoit Daloze) 2 months ago
          Updated by Eregon (Benoit Daloze) 2 months ago
          
          
        
        
      
      The CI did pass on Windows e.g. https://github.com/ruby/pathname/actions/runs/16760570256/job/47454475161
Are there extra Pathname tests in CRuby?
In any case, happy to take a look.