https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2017-05-24T06:57:14Z
Ruby Issue Tracking System
Ruby master - Bug #13553: Improve performance in where push the element into non shared Array object
https://redmine.ruby-lang.org/issues/13553?journal_id=65068
2017-05-24T06:57: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|r58867.</p>
<hr>
<p>Improve performance in where push the element into non shared Array object</p>
<ul>
<li>
<p>array.c (ary_ensure_room_for_push): use rb_ary_modify_check() instead of<br>
rb_ary_modify() to check whether the object can be modified for non shared<br>
Array object. rb_ary_modify() has the codes for shared Array object too.<br>
In here, it has condition branch for shared / non shared Array object and<br>
it can use rb_ary_modify_check() which is smaller function than<br>
rb_ary_modify() for non shared object.</p>
<p>rb_ary_modify_check() will be expand as inline function.<br>
If it will compile with GCC, Array#<< will be faster around 8%.</p>
<p><a href="/issues/13553">[ruby-core:81082]</a> [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance in where push the element into non shared Array object (Closed)" href="https://redmine.ruby-lang.org/issues/13553">#13553</a>] [Fix GH-1609]</p>
</li>
</ul>
<a name="Clang-802042"></a>
<h2 >Clang 802.0.42<a href="#Clang-802042" class="wiki-anchor">¶</a></h2>
<a name="Before"></a>
<h3 >Before<a href="#Before" class="wiki-anchor">¶</a></h3>
<pre><code> Array#<< 9.353M (± 1.7%) i/s - 46.787M in 5.004123s
Array#push 7.702M (± 1.1%) i/s - 38.577M in 5.009338s
Array#values_at 6.133M (± 1.9%) i/s - 30.699M in 5.007772s
</code></pre>
<a name="After"></a>
<h3 >After<a href="#After" class="wiki-anchor">¶</a></h3>
<pre><code> Array#<< 9.458M (± 2.0%) i/s - 47.357M in 5.009069s
Array#push 7.921M (± 1.8%) i/s - 39.665M in 5.009151s
Array#values_at 6.377M (± 2.3%) i/s - 31.881M in 5.001888s
</code></pre>
<a name="Result"></a>
<h3 >Result<a href="#Result" class="wiki-anchor">¶</a></h3>
<p>Array#<< -> 1.2% faster<br>
Array#push -> 2.8% faster<br>
Array#values_at -> 3.9% faster</p>
<a name="GCC-710"></a>
<h2 >GCC 7.1.0<a href="#GCC-710" class="wiki-anchor">¶</a></h2>
<a name="Before-2"></a>
<h3 >Before<a href="#Before-2" class="wiki-anchor">¶</a></h3>
<pre><code> Array#<< 10.497M (± 1.1%) i/s - 52.665M in 5.017601s
Array#push 8.527M (± 1.6%) i/s - 42.777M in 5.018003s
Array#values_at 7.621M (± 1.7%) i/s - 38.152M in 5.007910s
</code></pre>
<a name="After-2"></a>
<h3 >After<a href="#After-2" class="wiki-anchor">¶</a></h3>
<pre><code> Array#<< 11.403M (± 1.3%) i/s - 57.028M in 5.001849s
Array#push 8.924M (± 1.3%) i/s - 44.609M in 4.999940s
Array#values_at 8.291M (± 1.4%) i/s - 41.487M in 5.004727s
</code></pre>
<a name="Result-2"></a>
<h3 >Result<a href="#Result-2" class="wiki-anchor">¶</a></h3>
<p>Array#<< -> 8.3% faster<br>
Array#push -> 4.3% faster<br>
Array#values_at -> 8.7% faster</p>
<a name="Test-code"></a>
<h2 >Test code<a href="#Test-code" class="wiki-anchor">¶</a></h2>
<p>require 'benchmark/ips'</p>
<p>Benchmark.ips do |x|</p>
<p>x.report "Array#<<" do |i|<br>
i.times { [1,2] << 3 }<br>
end</p>
<p>x.report "Array#push" do |i|<br>
i.times { [1,2].push(3) }<br>
end</p>
<p>x.report "Array#values_at" do |i|<br>
ary = [1, 2, 3, 4, 5]<br>
i.times { ary.values_at(0, 2, 4) }<br>
end</p>
<p>end</p>