https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2018-03-13T09:15:14Z
Ruby Issue Tracking System
Ruby master - Bug #14599: Improve Pathname performance
https://redmine.ruby-lang.org/issues/14599?journal_id=70966
2018-03-13T09:15:14Z
watson1978 (Shizuo Fujita)
watson1978@gmail.com
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>Applied in changeset trunk|r62740.</p>
<hr>
<p>Improve Pathname performance</p>
<p>If it will not use special variables (like $1, $&, $`...),<br>
it can improve the performance by using Regexp#match? instead of Regexp#=~.<br>
Because Regexp#=~ will generate the objects to special variables by pattern matching.</p>
<p>This patch will replace Regexp#=~ without special variables to Regexp#match?.<br>
(Excludes <a href="https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L144-L153" class="external">https://github.com/ruby/ruby/blob/trunk/ext/pathname/lib/pathname.rb#L144-L153</a>)</p>
<p>[Fix GH-1836] <a href="/issues/14599">[ruby-core:86093]</a> [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve Pathname performance (Closed)" href="https://redmine.ruby-lang.org/issues/14599">#14599</a>]</p>
<a name="Environment"></a>
<h2 >Environment<a href="#Environment" class="wiki-anchor">¶</a></h2>
<ul>
<li>OS : Ubuntu 17.10</li>
<li>Compiler : gcc version 7.2.0</li>
<li>CPU : Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz</li>
<li>Memory : 16 GB</li>
</ul>
<a name="TLDR"></a>
<h2 >TL;DR<a href="#TLDR" class="wiki-anchor">¶</a></h2>
<table>
<thead>
<tr>
<th> </th>
<th>Before</th>
<th>After</th>
<th>Speed up</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pathname#absolute?</td>
<td>142836</td>
<td>198487</td>
<td>39.0%</td>
</tr>
<tr>
<td>Pathname#cleanpath</td>
<td>60706</td>
<td>79415</td>
<td>30.8%</td>
</tr>
<tr>
<td>Pathname#root?</td>
<td>603806</td>
<td>759157</td>
<td>25.7%</td>
</tr>
<tr>
<td>Pathname#absolute?</td>
<td>142592</td>
<td>197859</td>
<td>38.8%</td>
</tr>
<tr>
<td>Pathname#each_filename</td>
<td>115600</td>
<td>152982</td>
<td>32.3%</td>
</tr>
<tr>
<td>Pathname#ascend</td>
<td>50494</td>
<td>63606</td>
<td>26.0%</td>
</tr>
<tr>
<td>Pathname#+</td>
<td>100550</td>
<td>130372</td>
<td>29.7%</td>
</tr>
<tr>
<td>Pathname#join</td>
<td>46673</td>
<td>60994</td>
<td>30.7%</td>
</tr>
<tr>
<td>Pathname#relative_path_from</td>
<td>28362</td>
<td>37494</td>
<td>32.2%</td>
</tr>
</tbody>
</table>
<a name="Before"></a>
<h2 >Before<a href="#Before" class="wiki-anchor">¶</a></h2>
<pre><code>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
</code></pre>
<a name="After"></a>
<h2 >After<a href="#After" class="wiki-anchor">¶</a></h2>
<pre><code>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
</code></pre>
<a name="Benchmark-code"></a>
<h2 >Benchmark code<a href="#Benchmark-code" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'pathname'</span>
<span class="nb">require</span> <span class="s1">'benchmark/ips'</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">ips</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="n">root</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span>
<span class="n">path1</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/path/to/some/file1.rb'</span><span class="p">)</span>
<span class="n">path2</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/path/to/some/file2.rb'</span><span class="p">)</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#absolute?"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">absolute?</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#cleanpath"</span><span class="p">)</span> <span class="k">do</span>
<span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/path/to/some/file.rb'</span><span class="p">).</span><span class="nf">cleanpath</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#root?"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">root?</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#absolute?"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">absolute?</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#each_filename"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">each_filename</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#ascend"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">ascend</span> <span class="p">{</span> <span class="o">|</span><span class="n">path</span><span class="o">|</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#+"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span> <span class="o">+</span> <span class="n">path2</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#join"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">"../file3.rb"</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Pathname#relative_path_from"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">path1</span><span class="p">.</span><span class="nf">relative_path_from</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>