https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112017-04-15T07:51:40ZRuby Issue Tracking SystemRuby master - Bug #13341: Improve performance of implicit type conversionhttps://bugs.ruby-lang.org/issues/13341?journal_id=642392017-04-15T07:51:40Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>+cc ruby-core since this post was English</p>
<p><a href="mailto:watson1978@gmail.com" class="email">watson1978@gmail.com</a> wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance of implicit type conversion (Closed)" href="https://bugs.ruby-lang.org/issues/13341">#13341</a> has been reported by watson1978 (Shizuo Fujita).</p>
<hr>
<p>Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance of implicit type conversion (Closed)" href="https://bugs.ruby-lang.org/issues/13341">#13341</a>: Improve performance of implicit type conversion<br>
<a href="https://bugs.ruby-lang.org/issues/13341" class="external">https://bugs.ruby-lang.org/issues/13341</a></p>
</blockquote>
<p>Interesting...</p>
<blockquote>
<hr>
<p>At least, Array#flatten will be faster around 20%.<br>
Seems that strncmp() & strcmp() in convert_type() are slightly heavy to look up the method's id for type conversion.<br>
(<a href="https://github.com/ruby/ruby/blob/4f2db15b42d7b8eb5b304a92ba2296632dba3edf/object.c#L2634-L2643" class="external">https://github.com/ruby/ruby/blob/4f2db15b42d7b8eb5b304a92ba2296632dba3edf/object.c#L2634-L2643</a>)</p>
<p>This patch will use known method's id directly.</p>
<a name="Before"></a>
<h3 >Before<a href="#Before" class="wiki-anchor">¶</a></h3>
<pre><code> user system total real
Array#flatten (rb_check_convert_type2) 1.000000 0.000000 1.000000 ( 1.001917)
Array#+ (rb_convert_type2) 1.010000 0.000000 1.010000 ( 1.006383)
</code></pre>
<a name="After"></a>
<h3 >After<a href="#After" class="wiki-anchor">¶</a></h3>
<pre><code> user system total real
Array#flatten (rb_check_convert_type2) 0.830000 0.000000 0.830000 ( 0.833411)
Array#+ (rb_convert_type2) 0.950000 0.000000 0.950000 ( 0.953832)
</code></pre>
</blockquote>
<blockquote>
<p>The patch is in <a href="https://github.com/ruby/ruby/pull/1537" class="external">https://github.com/ruby/ruby/pull/1537</a></p>
</blockquote>
<p>I use "fetch = +refs/pull/<em>:refs/remotes/pull/</em>" in my<br>
.git/config to check pull/1537/head in ruby.git without using<br>
only standard git (no proprietary JavaScript) and<br>
looked at following commits:</p>
<p>e189f53a26 use rb_convert_type2() for #to_r<br>
5e836acef6 Improve performance of implicit type conversion</p>
<p>So yes, I hate strcmp/strncmp, too.</p>
<p>If we change the API, I prefer we drastically shorten<br>
the function args for common case types.</p>
<p>I'm not sure if including new APIs in ruby/intern.h is a good<br>
idea right away, since that is technically public API.</p>
<p>Perhaps keep it in internal.h for now.</p>
<p>So, maybe:</p>
<pre><code> rb_convert_type2(a1, idTo_a);
rb_convert_type2(a1, idTo_ary);
</code></pre>
<p>will lookup a small static table based on ID which fills in<br>
T_*** (and tname string for error reporting).</p>
<p>Corner cases like StringIO may use old API, maybe that is<br>
less critical.</p> Ruby master - Bug #13341: Improve performance of implicit type conversionhttps://bugs.ruby-lang.org/issues/13341?journal_id=642402017-04-15T07:51:40Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>+cc ruby-core since this post was English</p>
<p><a href="mailto:watson1978@gmail.com" class="email">watson1978@gmail.com</a> wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance of implicit type conversion (Closed)" href="https://bugs.ruby-lang.org/issues/13341">#13341</a> has been reported by watson1978 (Shizuo Fujita).</p>
<hr>
<p>Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance of implicit type conversion (Closed)" href="https://bugs.ruby-lang.org/issues/13341">#13341</a>: Improve performance of implicit type conversion<br>
<a href="https://bugs.ruby-lang.org/issues/13341" class="external">https://bugs.ruby-lang.org/issues/13341</a></p>
</blockquote>
<p>Interesting...</p>
<blockquote>
<hr>
<p>At least, Array#flatten will be faster around 20%.<br>
Seems that strncmp() & strcmp() in convert_type() are slightly heavy to look up the method's id for type conversion.<br>
(<a href="https://github.com/ruby/ruby/blob/4f2db15b42d7b8eb5b304a92ba2296632dba3edf/object.c#L2634-L2643" class="external">https://github.com/ruby/ruby/blob/4f2db15b42d7b8eb5b304a92ba2296632dba3edf/object.c#L2634-L2643</a>)</p>
<p>This patch will use known method's id directly.</p>
<a name="Before"></a>
<h3 >Before<a href="#Before" class="wiki-anchor">¶</a></h3>
<pre><code> user system total real
Array#flatten (rb_check_convert_type2) 1.000000 0.000000 1.000000 ( 1.001917)
Array#+ (rb_convert_type2) 1.010000 0.000000 1.010000 ( 1.006383)
</code></pre>
<a name="After"></a>
<h3 >After<a href="#After" class="wiki-anchor">¶</a></h3>
<pre><code> user system total real
Array#flatten (rb_check_convert_type2) 0.830000 0.000000 0.830000 ( 0.833411)
Array#+ (rb_convert_type2) 0.950000 0.000000 0.950000 ( 0.953832)
</code></pre>
</blockquote>
<blockquote>
<p>The patch is in <a href="https://github.com/ruby/ruby/pull/1537" class="external">https://github.com/ruby/ruby/pull/1537</a></p>
</blockquote>
<p>I use "fetch = +refs/pull/<em>:refs/remotes/pull/</em>" in my<br>
.git/config to check pull/1537/head in ruby.git without using<br>
only standard git (no proprietary JavaScript) and<br>
looked at following commits:</p>
<p>e189f53a26 use rb_convert_type2() for #to_r<br>
5e836acef6 Improve performance of implicit type conversion</p>
<p>So yes, I hate strcmp/strncmp, too.</p>
<p>If we change the API, I prefer we drastically shorten<br>
the function args for common case types.</p>
<p>I'm not sure if including new APIs in ruby/intern.h is a good<br>
idea right away, since that is technically public API.</p>
<p>Perhaps keep it in internal.h for now.</p>
<p>So, maybe:</p>
<pre><code> rb_convert_type2(a1, idTo_a);
rb_convert_type2(a1, idTo_ary);
</code></pre>
<p>will lookup a small static table based on ID which fills in<br>
T_*** (and tname string for error reporting).</p>
<p>Corner cases like StringIO may use old API, maybe that is<br>
less critical.</p> Ruby master - Bug #13341: Improve performance of implicit type conversionhttps://bugs.ruby-lang.org/issues/13341?journal_id=642412017-04-15T10:12:29Zwatson1978 (Shizuo Fujita)watson1978@gmail.com
<ul></ul><p>normalperson (Eric Wong) wrote:</p>
<blockquote>
<p>I'm not sure if including new APIs in ruby/intern.h is a good<br>
idea right away, since that is technically public API.</p>
<p>Perhaps keep it in internal.h for now.</p>
</blockquote>
<p>OK, moved them at <a href="https://github.com/ruby/ruby/pull/1537/commits/cfdbfb4c0d9269df9679de8793929130219e662d" class="external">https://github.com/ruby/ruby/pull/1537/commits/cfdbfb4c0d9269df9679de8793929130219e662d</a></p> Ruby master - Bug #13341: Improve performance of implicit type conversionhttps://bugs.ruby-lang.org/issues/13341?journal_id=651942017-05-31T12:31:03Zwatson1978 (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|r58978.</p>
<hr>
<p>Improve performance of implicit type conversion</p>
<p>To convert the object implicitly, it has had two parts in convert_type() which are</p>
<ol>
<li>lookink up the method's id</li>
<li>calling the method</li>
</ol>
<p>Seems that strncmp() and strcmp() in convert_type() are slightly heavy to look up<br>
the method's id for type conversion.</p>
<p>This patch will add and use internal APIs (rb_convert_type_with_id, rb_check_convert_type_with_id)<br>
to call the method without looking up the method's id when convert the object.</p>
<p>Array#flatten -> 19 % up<br>
Array#+ -> 3 % up</p>
<p><a href="/issues/13341">[ruby-dev:50024]</a> [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Improve performance of implicit type conversion (Closed)" href="https://bugs.ruby-lang.org/issues/13341">#13341</a>] [Fix GH-1537]</p>
<a name="Before"></a>
<h3 >Before<a href="#Before" class="wiki-anchor">¶</a></h3>
<pre><code> Array#flatten 104.119k (± 1.1%) i/s - 525.690k in 5.049517s
Array#+ 1.993M (± 1.8%) i/s - 10.010M in 5.024258s
</code></pre>
<a name="After"></a>
<h3 >After<a href="#After" class="wiki-anchor">¶</a></h3>
<pre><code> Array#flatten 124.005k (± 1.0%) i/s - 624.240k in 5.034477s
Array#+ 2.058M (± 4.8%) i/s - 10.302M in 5.019328s
</code></pre>
<a name="Test-Code"></a>
<h3 >Test Code<a href="#Test-Code" class="wiki-anchor">¶</a></h3>
<p>require 'benchmark/ips'</p>
<p>class Foo<br>
def to_ary<br>
[1,2,3]<br>
end<br>
end</p>
<p>Benchmark.ips do |x|</p>
<p>ary = []<br>
100.times { |i| ary << i }<br>
array = [ary]</p>
<p>x.report "Array#flatten" do |i|<br>
i.times { array.flatten }<br>
end</p>
<p>x.report "Array#+" do |i|<br>
obj = Foo.new<br>
i.times { array + obj }<br>
end</p>
<p>end</p>