Project

General

Profile

Bug #14599

Improve Pathname performance

Added by watson1978 (Shizuo Fujita) over 1 year ago. Updated over 1 year ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:86093]

Description

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)

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

  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 (± 0.1%) i/s -    722.304k in   5.056884s
  Pathname#cleanpath     60.706k (± 0.1%) i/s -    306.764k in   5.053305s
      Pathname#root?    603.806k (± 0.3%) i/s -      3.062M in   5.071696s
  Pathname#absolute?    142.592k (± 0.1%) i/s -    720.846k in   5.055301s
Pathname#each_filename
                        115.600k (± 0.1%) i/s -    586.818k in   5.076292s
     Pathname#ascend     50.494k (± 0.1%) i/s -    255.301k in   5.056049s
          Pathname#+    100.550k (± 0.1%) i/s -    509.630k in   5.068433s
       Pathname#join     46.673k (± 0.1%) i/s -    236.433k in   5.065696s
Pathname#relative_path_from
                         28.362k (± 0.0%) i/s -    143.728k in   5.067640s

After

Calculating -------------------------------------
  Pathname#absolute?    198.487k (± 0.1%) i/s -    995.665k in   5.016272s
  Pathname#cleanpath     79.415k (± 0.1%) i/s -    404.406k in   5.092344s
      Pathname#root?    759.157k (± 0.0%) i/s -      3.800M in   5.005072s
  Pathname#absolute?    197.859k (± 0.1%) i/s -    995.720k in   5.032494s
Pathname#each_filename
                        152.982k (± 0.1%) i/s -    775.555k in   5.069607s
     Pathname#ascend     63.606k (± 0.0%) i/s -    320.862k in   5.044560s
          Pathname#+    130.372k (± 0.1%) i/s -    660.856k in   5.068991s
       Pathname#join     60.994k (± 0.1%) i/s -    305.068k in   5.001626s
Pathname#relative_path_from
                         37.494k (± 0.4%) i/s -    189.124k in   5.044146s

Benchmark code

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

Patch

https://github.com/ruby/ruby/pull/1836

Associated revisions

Revision ccc25765
Added by watson1978 (Shizuo Fujita) over 1 year ago

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

  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 (± 0.1%) i/s -    722.304k in   5.056884s
  Pathname#cleanpath     60.706k (± 0.1%) i/s -    306.764k in   5.053305s
      Pathname#root?    603.806k (± 0.3%) i/s -      3.062M in   5.071696s
  Pathname#absolute?    142.592k (± 0.1%) i/s -    720.846k in   5.055301s
Pathname#each_filename
                        115.600k (± 0.1%) i/s -    586.818k in   5.076292s
     Pathname#ascend     50.494k (± 0.1%) i/s -    255.301k in   5.056049s
          Pathname#+    100.550k (± 0.1%) i/s -    509.630k in   5.068433s
       Pathname#join     46.673k (± 0.1%) i/s -    236.433k in   5.065696s
Pathname#relative_path_from
                         28.362k (± 0.0%) i/s -    143.728k in   5.067640s

After

Calculating -------------------------------------
  Pathname#absolute?    198.487k (± 0.1%) i/s -    995.665k in   5.016272s
  Pathname#cleanpath     79.415k (± 0.1%) i/s -    404.406k in   5.092344s
      Pathname#root?    759.157k (± 0.0%) i/s -      3.800M in   5.005072s
  Pathname#absolute?    197.859k (± 0.1%) i/s -    995.720k in   5.032494s
Pathname#each_filename
                        152.982k (± 0.1%) i/s -    775.555k in   5.069607s
     Pathname#ascend     63.606k (± 0.0%) i/s -    320.862k in   5.044560s
          Pathname#+    130.372k (± 0.1%) i/s -    660.856k in   5.068991s
       Pathname#join     60.994k (± 0.1%) i/s -    305.068k in   5.001626s
Pathname#relative_path_from
                         37.494k (± 0.4%) i/s -    189.124k in   5.044146s

Benchmark code

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

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62740 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 62740
Added by watson1978 (Shizuo Fujita) over 1 year ago

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

  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 (± 0.1%) i/s -    722.304k in   5.056884s
  Pathname#cleanpath     60.706k (± 0.1%) i/s -    306.764k in   5.053305s
      Pathname#root?    603.806k (± 0.3%) i/s -      3.062M in   5.071696s
  Pathname#absolute?    142.592k (± 0.1%) i/s -    720.846k in   5.055301s
Pathname#each_filename
                        115.600k (± 0.1%) i/s -    586.818k in   5.076292s
     Pathname#ascend     50.494k (± 0.1%) i/s -    255.301k in   5.056049s
          Pathname#+    100.550k (± 0.1%) i/s -    509.630k in   5.068433s
       Pathname#join     46.673k (± 0.1%) i/s -    236.433k in   5.065696s
Pathname#relative_path_from
                         28.362k (± 0.0%) i/s -    143.728k in   5.067640s

After

Calculating -------------------------------------
  Pathname#absolute?    198.487k (± 0.1%) i/s -    995.665k in   5.016272s
  Pathname#cleanpath     79.415k (± 0.1%) i/s -    404.406k in   5.092344s
      Pathname#root?    759.157k (± 0.0%) i/s -      3.800M in   5.005072s
  Pathname#absolute?    197.859k (± 0.1%) i/s -    995.720k in   5.032494s
Pathname#each_filename
                        152.982k (± 0.1%) i/s -    775.555k in   5.069607s
     Pathname#ascend     63.606k (± 0.0%) i/s -    320.862k in   5.044560s
          Pathname#+    130.372k (± 0.1%) i/s -    660.856k in   5.068991s
       Pathname#join     60.994k (± 0.1%) i/s -    305.068k in   5.001626s
Pathname#relative_path_from
                         37.494k (± 0.4%) i/s -    189.124k in   5.044146s

Benchmark code

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

Revision 62740
Added by watson1978 (Shizuo Fujita) over 1 year ago

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

  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 (± 0.1%) i/s -    722.304k in   5.056884s
  Pathname#cleanpath     60.706k (± 0.1%) i/s -    306.764k in   5.053305s
      Pathname#root?    603.806k (± 0.3%) i/s -      3.062M in   5.071696s
  Pathname#absolute?    142.592k (± 0.1%) i/s -    720.846k in   5.055301s
Pathname#each_filename
                        115.600k (± 0.1%) i/s -    586.818k in   5.076292s
     Pathname#ascend     50.494k (± 0.1%) i/s -    255.301k in   5.056049s
          Pathname#+    100.550k (± 0.1%) i/s -    509.630k in   5.068433s
       Pathname#join     46.673k (± 0.1%) i/s -    236.433k in   5.065696s
Pathname#relative_path_from
                         28.362k (± 0.0%) i/s -    143.728k in   5.067640s

After

Calculating -------------------------------------
  Pathname#absolute?    198.487k (± 0.1%) i/s -    995.665k in   5.016272s
  Pathname#cleanpath     79.415k (± 0.1%) i/s -    404.406k in   5.092344s
      Pathname#root?    759.157k (± 0.0%) i/s -      3.800M in   5.005072s
  Pathname#absolute?    197.859k (± 0.1%) i/s -    995.720k in   5.032494s
Pathname#each_filename
                        152.982k (± 0.1%) i/s -    775.555k in   5.069607s
     Pathname#ascend     63.606k (± 0.0%) i/s -    320.862k in   5.044560s
          Pathname#+    130.372k (± 0.1%) i/s -    660.856k in   5.068991s
       Pathname#join     60.994k (± 0.1%) i/s -    305.068k in   5.001626s
Pathname#relative_path_from
                         37.494k (± 0.4%) i/s -    189.124k in   5.044146s

Benchmark code

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

History

#1

Updated by watson1978 (Shizuo Fujita) over 1 year ago

  • Status changed from Open to Closed

Applied in changeset trunk|r62740.


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

  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 (± 0.1%) i/s -    722.304k in   5.056884s
  Pathname#cleanpath     60.706k (± 0.1%) i/s -    306.764k in   5.053305s
      Pathname#root?    603.806k (± 0.3%) i/s -      3.062M in   5.071696s
  Pathname#absolute?    142.592k (± 0.1%) i/s -    720.846k in   5.055301s
Pathname#each_filename
                        115.600k (± 0.1%) i/s -    586.818k in   5.076292s
     Pathname#ascend     50.494k (± 0.1%) i/s -    255.301k in   5.056049s
          Pathname#+    100.550k (± 0.1%) i/s -    509.630k in   5.068433s
       Pathname#join     46.673k (± 0.1%) i/s -    236.433k in   5.065696s
Pathname#relative_path_from
                         28.362k (± 0.0%) i/s -    143.728k in   5.067640s

After

Calculating -------------------------------------
  Pathname#absolute?    198.487k (± 0.1%) i/s -    995.665k in   5.016272s
  Pathname#cleanpath     79.415k (± 0.1%) i/s -    404.406k in   5.092344s
      Pathname#root?    759.157k (± 0.0%) i/s -      3.800M in   5.005072s
  Pathname#absolute?    197.859k (± 0.1%) i/s -    995.720k in   5.032494s
Pathname#each_filename
                        152.982k (± 0.1%) i/s -    775.555k in   5.069607s
     Pathname#ascend     63.606k (± 0.0%) i/s -    320.862k in   5.044560s
          Pathname#+    130.372k (± 0.1%) i/s -    660.856k in   5.068991s
       Pathname#join     60.994k (± 0.1%) i/s -    305.068k in   5.001626s
Pathname#relative_path_from
                         37.494k (± 0.4%) i/s -    189.124k in   5.044146s

Benchmark code

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

Also available in: Atom PDF