[前][次][番号順一覧][スレッド一覧]

ruby-changes:50592

From: watson1978 <ko1@a...>
Date: Tue, 13 Mar 2018 18:15:15 +0900 (JST)
Subject: [ruby-changes:50592] watson1978:r62740 (trunk): Improve Pathname performance

watson1978	2018-03-13 18:15:10 +0900 (Tue, 13 Mar 2018)

  New Revision: 62740

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62740

  Log:
    Improve Pathname performance
    
    If it will not use special variables (like $1, $&, $`...),
    it can improve the performance by using Regexp#match? instead of Regexp#=~.
    Because Regexp#=~ will generate the objects to special variables by pattern matching.
    
    This patch will replace Regexp#=~ without special variables to Regexp#match?.
    (Excludes https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L144-L153)
    
    [Fix GH-1836] [ruby-core:86093] [Bug #14599]
    
    ## Environment
    * OS : Ubuntu 17.10
    * Compiler : gcc version 7.2.0
    * CPU : Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
    * Memory : 16 GB
    
    ## TL;DR
    ?\194?\160                           | Before | After  | Speed up
    --------------------------- | ------ | ------ | --------
    Pathname#absolute?          | 142836 | 198487 | 39.0%
    Pathname#cleanpath          |  60706 |  79415 | 30.8%
    Pathname#root?              | 603806 | 759157 | 25.7%
    Pathname#absolute?          | 142592 | 197859 | 38.8%
    Pathname#each_filename      | 115600 | 152982 | 32.3%
    Pathname#ascend             |  50494 |  63606 | 26.0%
    Pathname#+                  | 100550 | 130372 | 29.7%
    Pathname#join               |  46673 |  60994 | 30.7%
    Pathname#relative_path_from |  28362 |  37494 | 32.2%
    
    ## Before
    ```
    Calculating -------------------------------------
      Pathname#absolute?    142.836k (?\194?\177 0.1%) i/s -    722.304k in   5.056884s
      Pathname#cleanpath     60.706k (?\194?\177 0.1%) i/s -    306.764k in   5.053305s
          Pathname#root?    603.806k (?\194?\177 0.3%) i/s -      3.062M in   5.071696s
      Pathname#absolute?    142.592k (?\194?\177 0.1%) i/s -    720.846k in   5.055301s
    Pathname#each_filename
                            115.600k (?\194?\177 0.1%) i/s -    586.818k in   5.076292s
         Pathname#ascend     50.494k (?\194?\177 0.1%) i/s -    255.301k in   5.056049s
              Pathname#+    100.550k (?\194?\177 0.1%) i/s -    509.630k in   5.068433s
           Pathname#join     46.673k (?\194?\177 0.1%) i/s -    236.433k in   5.065696s
    Pathname#relative_path_from
                             28.362k (?\194?\177 0.0%) i/s -    143.728k in   5.067640s
    ```
    
    ## After
    ```
    Calculating -------------------------------------
      Pathname#absolute?    198.487k (?\194?\177 0.1%) i/s -    995.665k in   5.016272s
      Pathname#cleanpath     79.415k (?\194?\177 0.1%) i/s -    404.406k in   5.092344s
          Pathname#root?    759.157k (?\194?\177 0.0%) i/s -      3.800M in   5.005072s
      Pathname#absolute?    197.859k (?\194?\177 0.1%) i/s -    995.720k in   5.032494s
    Pathname#each_filename
                            152.982k (?\194?\177 0.1%) i/s -    775.555k in   5.069607s
         Pathname#ascend     63.606k (?\194?\177 0.0%) i/s -    320.862k in   5.044560s
              Pathname#+    130.372k (?\194?\177 0.1%) i/s -    660.856k in   5.068991s
           Pathname#join     60.994k (?\194?\177 0.1%) i/s -    305.068k in   5.001626s
    Pathname#relative_path_from
                             37.494k (?\194?\177 0.4%) i/s -    189.124k in   5.044146s
    ```
    
    ## Benchmark code
    ```ruby
    require 'pathname'
    require 'benchmark/ips'
    
    Benchmark.ips do |x|
      root  = Pathname.new('/')
      path1 = Pathname.new('/path/to/some/file1.rb')
      path2 = Pathname.new('/path/to/some/file2.rb')
    
      x.report("Pathname#absolute?") do
        path1.absolute?
      end
    
      x.report("Pathname#cleanpath") do
        Pathname.new('/path/to/some/file.rb').cleanpath
      end
    
      x.report("Pathname#root?") do
        path1.root?
      end
    
      x.report("Pathname#absolute?") do
        path1.absolute?
      end
    
      x.report("Pathname#each_filename") do
        path1.each_filename { |file| }
      end
    
      x.report("Pathname#ascend") do
        path1.ascend { |path| }
      end
    
      x.report("Pathname#+") do
        path1 + path2
      end
    
      x.report("Pathname#join") do
        path1.join("../file3.rb")
      end
    
      x.report("Pathname#relative_path_from") do
        path1.relative_path_from(root)
      end
    end
    ```

  Modified files:
    trunk/ext/pathname/lib/pathname.rb
Index: ext/pathname/lib/pathname.rb
===================================================================
--- ext/pathname/lib/pathname.rb	(revision 62739)
+++ ext/pathname/lib/pathname.rb	(revision 62740)
@@ -40,7 +40,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L40
   # chop_basename(path) -> [pre-basename, basename] or nil
   def chop_basename(path) # :nodoc:
     base = File.basename(path)
-    if /\A#{SEPARATOR_PAT}?\z/o =~ base
+    if /\A#{SEPARATOR_PAT}?\z/o.match?(base)
       return nil
     else
       return path[0, path.rindex(base)], base
@@ -62,7 +62,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L62
   def prepend_prefix(prefix, relpath) # :nodoc:
     if relpath.empty?
       File.dirname(prefix)
-    elsif /#{SEPARATOR_PAT}/o =~ prefix
+    elsif /#{SEPARATOR_PAT}/o.match?(prefix)
       prefix = File.dirname(prefix)
       prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
       prefix + relpath
@@ -113,7 +113,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L113
       end
     end
     pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
-    if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
+    if /#{SEPARATOR_PAT}/o.match?(File.basename(pre))
       names.shift while names[0] == '..'
     end
     self.class.new(prepend_prefix(pre, File.join(*names)))
@@ -162,7 +162,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L162
       names.unshift base if base != '.'
     end
     pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
-    if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
+    if /#{SEPARATOR_PAT}/o.match?(File.basename(pre))
       names.shift while names[0] == '..'
     end
     if names.empty?
@@ -208,7 +208,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L208
   # pathnames which points to roots such as <tt>/usr/..</tt>.
   #
   def root?
-    !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path)
+    !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o.match?(@path))
   end
 
   # Predicate method for testing whether a path is absolute.
@@ -380,7 +380,7 @@ class Pathname https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L380
       basename_list2.shift
     end
     r1 = chop_basename(prefix1)
-    if !r1 && (r1 = /#{SEPARATOR_PAT}/o =~ File.basename(prefix1))
+    if !r1 && (r1 = /#{SEPARATOR_PAT}/o.match?(File.basename(prefix1)))
       while !basename_list2.empty? && basename_list2.first == '..'
         index_list2.shift
         basename_list2.shift

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]