https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112010-10-30T17:59:43ZRuby Issue Tracking SystemRuby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=139592010-10-30T17:59:43Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>=begin<br>
2010/10/5, Eric Wong <a href="mailto:redmine@ruby-lang.org" class="email">redmine@ruby-lang.org</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: rb_clear_cache_by_class() called often during GC for non-blocking I/O (Closed)" href="https://redmine.ruby-lang.org/issues/3905">#3905</a>: rb_clear_cache_by_class() called often during GC for<br>
non-blocking I/O<br>
<a href="http://redmine.ruby-lang.org/issues/show/3905" class="external">http://redmine.ruby-lang.org/issues/show/3905</a></p>
</blockquote>
<blockquote>
<p>This still causes performance problems with frequent EAGAIN compared to<br>
1.9.1</p>
<p>While akr fixed extend to no longer clear cache with empty modules in<br>
r28813,<br>
the GC phase still scans and clears the cache when the extended object is<br>
collected.</p>
</blockquote>
<p>The following patch fix the problem?</p>
<h1>% svn diff --diff-cmd diff -x '-u -p'<br>
Index: gc.c</h1>
<p>--- gc.c (revision 29630)<br>
+++ gc.c (working copy)<br>
@@ -2210,7 +2210,8 @@ obj_free(rb_objspace_t *objspace, VALUE<br>
break;<br>
case T_MODULE:<br>
case T_CLASS:</p>
<ul>
<li>rb_clear_cache_by_class((VALUE)obj);</li>
</ul>
<ul>
<li>
<pre><code> if (RCLASS_M_TBL(obj)->num_entries != 0)
</code></pre>
</li>
<li>
<pre><code> rb_clear_cache_by_class((VALUE)obj);
</code></pre>
rb_free_m_table(RCLASS_M_TBL(obj));<br>
if (RCLASS_IV_TBL(obj)) {<br>
st_free_table(RCLASS_IV_TBL(obj));<br>
--<br>
Tanaka Akira</li>
</ul>
<p>=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=139832010-11-01T21:18:31Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>=begin<br>
2010/10/30 Tanaka Akira <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a>:</p>
<blockquote>
<p>2010/10/5, Eric Wong <a href="mailto:redmine@ruby-lang.org" class="email">redmine@ruby-lang.org</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: rb_clear_cache_by_class() called often during GC for non-blocking I/O (Closed)" href="https://redmine.ruby-lang.org/issues/3905">#3905</a>: rb_clear_cache_by_class() called often during GC for<br>
non-blocking I/O<br>
<a href="http://redmine.ruby-lang.org/issues/show/3905" class="external">http://redmine.ruby-lang.org/issues/show/3905</a></p>
</blockquote>
<blockquote>
<p>This still causes performance problems with frequent EAGAIN compared to<br>
1.9.1</p>
<p>While akr fixed extend to no longer clear cache with empty modules in<br>
r28813,<br>
the GC phase still scans and clears the cache when the extended object is<br>
collected.</p>
</blockquote>
<p>The following patch fix the problem?</p>
</blockquote>
<p>The following patch may be better.</p>
<h1>% svn diff --diff-cmd diff -x '-u -p'<br>
Index: vm_method.c</h1>
<p>--- vm_method.c (revision 29630)<br>
+++ vm_method.c (working copy)<br>
@@ -85,6 +85,9 @@ rb_clear_cache_by_class(VALUE klass)<br>
{<br>
struct cache_entry *ent, *end;</p>
<ul>
<li>
<p>if (RCLASS_M_TBL(klass)->num_entries == 0)</p>
</li>
<li>
<pre><code> return;
</code></pre>
</li>
<li>
<p>rb_vm_change_state();</p>
<p>if (!ruby_running)<br>
--<br>
Tanaka Akira</p>
</li>
</ul>
<p>=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=140102010-11-03T04:25:35Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>=begin<br>
Tanaka Akira <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a> wrote:</p>
<blockquote>
<p>2010/10/30 Tanaka Akira <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a>:</p>
<blockquote>
<p>2010/10/5, Eric Wong <a href="mailto:redmine@ruby-lang.org" class="email">redmine@ruby-lang.org</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: rb_clear_cache_by_class() called often during GC for non-blocking I/O (Closed)" href="https://redmine.ruby-lang.org/issues/3905">#3905</a>: rb_clear_cache_by_class() called often during GC for<br>
non-blocking I/O<br>
<a href="http://redmine.ruby-lang.org/issues/show/3905" class="external">http://redmine.ruby-lang.org/issues/show/3905</a></p>
</blockquote>
<blockquote>
<p>This still causes performance problems with frequent EAGAIN compared to<br>
1.9.1</p>
<p>While akr fixed extend to no longer clear cache with empty modules in<br>
r28813,<br>
the GC phase still scans and clears the cache when the extended object is<br>
collected.</p>
</blockquote>
<p>The following patch fix the problem?</p>
</blockquote>
<p>The following patch may be better.</p>
</blockquote>
<p>Yes, I've only tried the second one as it looks cleaner and it brings<br>
non-blocking I/O performance back up to 1.9.1 levels.</p>
<p>Thank you!</p>
<p>--<br>
Eric Wong</p>
<p>=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=140142010-11-03T07:47:06Zakr (Akira Tanaka)akr@fsij.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>=begin<br>
This issue was solved with changeset r29673.<br>
Eric, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<p>=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=167082011-04-29T10:32:00Zkosaki (Motohiro KOSAKI)kosaki.motohiro@gmail.com
<ul></ul><p>=begin<br>
r29673 caused a regression (see [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Timeouts in threads cause SEGV (Closed)" href="https://redmine.ruby-lang.org/issues/4289">#4289</a>]). Then, I reverted it by r31378.<br>
Alternative fixing way is discussed by [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Timeouts in threads cause SEGV (Closed)" href="https://redmine.ruby-lang.org/issues/4289">#4289</a>] thread.<br>
=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=167182011-04-30T03:23:07Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>=begin<br>
Motohiro KOSAKI <a href="mailto:kosaki.motohiro@gmail.com" class="email">kosaki.motohiro@gmail.com</a> wrote:</p>
<blockquote>
<p>r29673 caused a regression (see [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Timeouts in threads cause SEGV (Closed)" href="https://redmine.ruby-lang.org/issues/4289">#4289</a>]). Then, I reverted it by r31378.<br>
Alternative fixing way is discussed by [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Timeouts in threads cause SEGV (Closed)" href="https://redmine.ruby-lang.org/issues/4289">#4289</a>] thread.</p>
</blockquote>
<p>I've pushed the ephemeral class patches up to a new branch:</p>
<p>$ git pull git://bogomips.org/ruby ephemeral-class</p>
<pre><code> 1) introduce ephemeral class flag for short lived class
2) vm_method.c: ephemeral classes do not write/expire cache
3) IO::Wait*able-extended singleton classes are ephemeral
</code></pre>
<p>--<br>
Eric Wong<br>
=end</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=170282011-05-17T23:16:52Zakr (Akira Tanaka)akr@fsij.org
<ul><li><strong>Status</strong> changed from <i>Closed</i> to <i>Open</i></li></ul><p>Sorry for late reply.</p>
<p>I'd like to incorporate 0001-error.c-rb_mod_sys_fail-use-subclass-and-cache.patch.</p>
<p>Although I'm not sure how to view the ephemeral class patches (I don't know git well), I guess it is too intrusive.</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=170312011-05-18T02:59:29Znormalperson (Eric Wong)normalperson@yhbt.net
<ul><li><strong>File</strong> <a href="/attachments/1703">full-ephemeral-class.diff</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/1703/full-ephemeral-class.diff">full-ephemeral-class.diff</a> added</li></ul><p>I think subclassing + cache broke some testcases with my updated patch:<br>
<a href="http://redmine.ruby-lang.org/issues/4289#note-5" class="external">http://redmine.ruby-lang.org/issues/4289#note-5</a></p>
<p>The ephemeral class patch series is smaller and cleaner, it makes<br>
no user-visible changes.</p>
<p>Somehow, I think I managed to upload the patches to <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Timeouts in threads cause SEGV (Closed)" href="https://redmine.ruby-lang.org/issues/4289">#4289</a> incorrectly.</p>
<p>I'm uploading a full diff for ephemeral-class since it's small.</p>
<p>Also if you want to try git:</p>
<a name="get-official-mirror"></a>
<h1 >get official mirror<a href="#get-official-mirror" class="wiki-anchor">¶</a></h1>
<p>git clone git://github.com/ruby/ruby.git</p>
<p>cd ruby</p>
<a name="add-my-repo-and-fetch"></a>
<h1 >add my repo and fetch<a href="#add-my-repo-and-fetch" class="wiki-anchor">¶</a></h1>
<p>git remote add bogomips git://bogomips.org/ruby<br>
git fetch bogomips</p>
<a name="view-diff-of-trunk-to-my-ephemeral-class-branch"></a>
<h1 >view diff of trunk to my ephemeral-class branch<a href="#view-diff-of-trunk-to-my-ephemeral-class-branch" class="wiki-anchor">¶</a></h1>
<p>git diff origin/trunk bogomips/ephemeral-class</p>
<a name="view-patch-series-of-trunk-to-my-ephemeral-class-branch"></a>
<h1 >view patch series of trunk to my ephemeral-class branch<a href="#view-patch-series-of-trunk-to-my-ephemeral-class-branch" class="wiki-anchor">¶</a></h1>
<p>git log -p origin/trunk..bogomips/ephemeral-class</p>
<a name="export-patch-series-of-trunk-to-my-ephemeral-class-branch"></a>
<h1 >export patch series of trunk to my ephemeral-class branch<a href="#export-patch-series-of-trunk-to-my-ephemeral-class-branch" class="wiki-anchor">¶</a></h1>
<a name="this-will-output-filenames-of-mbox-patches-it-makes"></a>
<h1 >(this will output filenames of mbox patches it makes)<a href="#this-will-output-filenames-of-mbox-patches-it-makes" class="wiki-anchor">¶</a></h1>
<p>git format-patch origin/trunk..bogomips/ephemeral-class</p>
<p>I also have a web viewer: <a href="http://bogomips.org/ruby.git?h=ephemeral-class" class="external">http://bogomips.org/ruby.git?h=ephemeral-class</a></p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=170382011-05-18T04:23:14Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>The ephemeral class patch series is smaller and cleaner, it makes<br>
no user-visible changes.</p>
</blockquote>
<p>The ephemeral class flag can eventually be expanded for use in other<br>
modules, not just I/O ones.</p>
<p>The unique subclass used in timeout.rb to distinguish nested timeouts<br>
is one example (especially if we decide to rewrite timeout.rb in C).</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=170932011-05-19T22:52:52Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>I don't against for the ephemeral class flag but<br>
it needs discussion with ko1 and/or matz.</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=175512011-06-07T02:59:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Akira Tanaka <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a> wrote:</p>
<blockquote>
<p>I don't against for the ephemeral class flag but<br>
it needs discussion with ko1 and/or matz.</p>
</blockquote>
<p>Can either of them comment please? I would really like to see<br>
this performance regression fixed in 1.9.3.</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=175882011-06-08T16:51:08Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>What's the effect of the EPHEMERAL flag if someone takes an object with an attached ephemeral class and starts making singleton changes to that object? Do those changes properly flush cache?</p>
<p>If this flag only helps cases where you're extending a module with no methods, it seems extremely niche...why don't we just reverse course on extending these modules at all?</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176162011-06-09T06:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Charles Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>What's the effect of the EPHEMERAL flag if someone takes an object<br>
with an attached ephemeral class and starts making singleton changes<br>
to that object? Do those changes properly flush cache?</p>
</blockquote>
<p>No, it's a situation where the user must be careful and not shoot<br>
themselves in the foot. It is C, after all.</p>
<p>Nowadays since internal.h exists, it would be safer to only expose<br>
ephemeral in the new "internal.h" header and not make it part of the<br>
public C API.</p>
<blockquote>
<p>If this flag only helps cases where you're extending a module with no<br>
methods, it seems extremely niche...why don't we just reverse course<br>
on extending these modules at all?</p>
</blockquote>
<p>This would break code already written for Ruby 1.9.2. Otherwise, I<br>
would love to do it (not that I have the power to actually do it).</p>
<p>I absolutely <em>HATE</em> the way Ruby extends classes and throws exceptions<br>
for EAGAIN, but there's not much one can do about it.</p>
<p>A better idea would be to get a kgio-like API into Ruby itself and<br>
encourage people to start using that. kgio itself will never take off<br>
since it's *nix-only and written in C, so it should be moved into Ruby<br>
and the Ruby spec itself if people really want it (without the ugly<br>
"kgio_" prefixes everywhere).</p>
<p>[1] - <a href="http://bogomips.org/kgio/" class="external">http://bogomips.org/kgio/</a></p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176252011-06-09T14:23:06Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>On Wed, Jun 8, 2011 at 4:00 PM, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>Charles Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>What's the effect of the EPHEMERAL flag if someone takes an object<br>
with an attached ephemeral class and starts making singleton changes<br>
to that object? Do those changes properly flush cache?</p>
</blockquote>
<p>No, it's a situation where the user must be careful and not shoot<br>
themselves in the foot. It is C, after all.</p>
</blockquote>
<p>But isn't this an exception object that will be raised into Ruby code?<br>
In other words...</p>
<p>begin<br>
io.read_nonblock<br>
rescue WaitReadable => e<br>
class << self<br>
# add something cute<br>
end<br>
end</p>
<blockquote>
<blockquote>
<p>If this flag only helps cases where you're extending a module with no<br>
methods, it seems extremely niche...why don't we just reverse course<br>
on extending these modules at all?</p>
</blockquote>
<p>This would break code already written for Ruby 1.9.2. Otherwise, I<br>
would love to do it (not that I have the power to actually do it).</p>
<p>I absolutely <em>HATE</em> the way Ruby extends classes and throws exceptions<br>
for EAGAIN, but there's not much one can do about it.</p>
</blockquote>
<p>Ok, I'm glad we agree here :) In fact, here's the code that extends<br>
WaitReadable in JRuby:</p>
<p>// FIXME: <em>oif</em> 1.9 actually does this<br>
if (ruby.is1_9()) {<br>
eagain.getException().extend(new IRubyObject[]<br>
{ruby.getIO().getConstant("WaitReadable")});<br>
}</p>
<p>Perhaps I should also express my disapproval through song?</p>
<blockquote>
<p>A better idea would be to get a kgio-like API into Ruby itself and<br>
encourage people to start using that. kgio itself will never take off<br>
since it's *nix-only and written in C, so it should be moved into Ruby<br>
and the Ruby spec itself if people really want it (without the ugly<br>
"kgio_" prefixes everywhere).</p>
</blockquote>
<p>At least on the JRuby side of things, I'd love to build this in as a<br>
shipping (but nonstandard) library. Java's NIO has similar goals in<br>
mind...specifically, if you need to try again on a nonblocking read,<br>
it just returns a boolean rather than raising some big heavy error. In<br>
fact, kgio may map very well to NIO, at least for the common cases.</p>
<p>Interested in the overhead of this EAGAIN nonsense, I ran a quick<br>
benchmark. I include it here for the amusement of all. It demonstrates<br>
pretty clearly the impact of the extend(WaitReadable), since that's<br>
really the only thing that differs between the two (at least in<br>
JRuby).</p>
<p>~/projects/jruby ➔ ruby -v -rbenchmark -rsocket -e "def<br>
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue<br>
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times<br>
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {<br>
loop_eagain(sock) } }<br>
"<br>
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]<br>
0.110000 0.020000 0.130000 ( 0.130989)<br>
0.110000 0.020000 0.130000 ( 0.128334)<br>
0.110000 0.020000 0.130000 ( 0.135947)<br>
0.110000 0.020000 0.130000 ( 0.131490)<br>
0.110000 0.020000 0.130000 ( 0.131814)<br>
0.110000 0.020000 0.130000 ( 0.132031)<br>
0.110000 0.020000 0.130000 ( 0.129517)<br>
0.110000 0.020000 0.130000 ( 0.128233)<br>
0.110000 0.020000 0.130000 ( 0.128804)<br>
0.110000 0.020000 0.130000 ( 0.127877)</p>
<p>~/projects/jruby ➔ ruby1.9 -v -rbenchmark -rsocket -e "def<br>
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue<br>
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times<br>
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {<br>
loop_eagain(sock) } }<br>
"<br>
ruby 1.9.2p160 (2011-01-16 revision 30579) [x86_64-darwin10.6.0]<br>
0.260000 0.030000 0.290000 ( 0.287646)<br>
0.280000 0.030000 0.310000 ( 0.315121)<br>
0.260000 0.020000 0.280000 ( 0.288908)<br>
0.270000 0.030000 0.300000 ( 0.291922)<br>
0.260000 0.020000 0.280000 ( 0.292273)<br>
0.270000 0.020000 0.290000 ( 0.301361)<br>
0.260000 0.030000 0.290000 ( 0.291552)<br>
0.270000 0.020000 0.290000 ( 0.298062)<br>
0.270000 0.030000 0.300000 ( 0.337271)<br>
0.280000 0.040000 0.320000 ( 0.348292)</p>
<p>~/projects/jruby ➔ jruby -v -rbenchmark -rsocket -e "def<br>
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue<br>
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times<br>
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {<br>
loop_eagain(sock) } }<br>
"<br>
jruby 1.7.0.dev (ruby-1.8.7-p330) (2011-06-08 c1029d9) (Java<br>
HotSpot(TM) 64-Bit Server VM 1.6.0_22) [darwin-x86_64-java]<br>
1.102000 0.000000 1.102000 ( 1.051000)<br>
0.583000 0.000000 0.583000 ( 0.583000)<br>
0.607000 0.000000 0.607000 ( 0.607000)<br>
0.120000 0.000000 0.120000 ( 0.120000)<br>
0.119000 0.000000 0.119000 ( 0.119000)<br>
0.123000 0.000000 0.123000 ( 0.123000)<br>
0.113000 0.000000 0.113000 ( 0.113000)<br>
0.120000 0.000000 0.120000 ( 0.120000)<br>
0.124000 0.000000 0.124000 ( 0.124000)<br>
0.117000 0.000000 0.117000 ( 0.117000)</p>
<p>~/projects/jruby ➔ jruby --1.9 -v -rbenchmark -rsocket -e "def<br>
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue<br>
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times<br>
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {<br>
loop_eagain(sock) } }<br>
"<br>
jruby 1.7.0.dev (ruby-1.9.2-p136) (2011-06-08 c1029d9) (Java<br>
HotSpot(TM) 64-Bit Server VM 1.6.0_22) [darwin-x86_64-java]<br>
1.965000 0.000000 1.965000 ( 1.964000)<br>
1.369000 0.000000 1.369000 ( 1.369000)<br>
0.712000 0.000000 0.712000 ( 0.712000)<br>
0.567000 0.000000 0.567000 ( 0.566000)<br>
0.208000 0.000000 0.208000 ( 0.208000)<br>
0.209000 0.000000 0.209000 ( 0.209000)<br>
0.204000 0.000000 0.204000 ( 0.204000)<br>
0.207000 0.000000 0.207000 ( 0.207000)<br>
0.207000 0.000000 0.207000 ( 0.206000)<br>
0.213000 0.000000 0.213000 ( 0.212000)</p>
<ul>
<li>Charlie</li>
</ul> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176262011-06-09T17:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Charles Oliver Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>On Wed, Jun 8, 2011 at 4:00 PM, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>Charles Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>What's the effect of the EPHEMERAL flag if someone takes an object<br>
with an attached ephemeral class and starts making singleton changes<br>
to that object? Do those changes properly flush cache?</p>
</blockquote>
</blockquote>
</blockquote>
<p>Nevermind, I misread the first time and got ordering of your question<br>
mixed up in my mind.</p>
<p>Once a class is tagged RCLASS_EPHEMERAL, it's impossible for it to<br>
write to the cache. There's no need to flush the cache for ephemeral<br>
classes because...</p>
<blockquote>
<blockquote>
<p>No, it's a situation where the user must be careful and not shoot<br>
themselves in the foot. ??It is C, after all.</p>
</blockquote>
</blockquote>
<p>...the the /only/ safe way to use RCLASS_EPHEMERAL is before any methods<br>
are called (and cached) for the singleton class.</p>
<blockquote>
<p>But isn't this an exception object that will be raised into Ruby code?<br>
In other words...</p>
<p>begin<br>
io.read_nonblock<br>
rescue WaitReadable => e<br>
class << self<br>
# add something cute</p>
</blockquote>
<p>Any methods defined here will never be cached, because RCLASS_EPHEMERAL<br>
was set before we re-entered Ruby-land.</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176272011-06-09T17:53:07Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Charles Oliver Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>Interested in the overhead of this EAGAIN nonsense, I ran a quick<br>
benchmark. I include it here for the amusement of all. It demonstrates<br>
pretty clearly the impact of the extend(WaitReadable), since that's<br>
really the only thing that differs between the two (at least in<br>
JRuby).</p>
</blockquote>
<p>Since you provided the benchmark code, I reformatted and<br>
made a version of it for kgio (see below).</p>
<p>Summary: ephemeral-class performance noticeably (and will have<br>
a bigger impact for bigger applications, not small benchmark scripts)</p>
<p>kgio reduces overhead greatly by avoiding exceptions. Real-world<br>
results (see the dalli README) are less impressive, of course, but still<br>
noticeable.</p>
<p>Results below:</p>
<p>== Ruby trunk<br>
ruby 1.9.3dev (2011-06-09 trunk 31961) [x86_64-linux]<br>
0.150000 0.000000 0.150000 ( 0.158108)<br>
0.150000 0.000000 0.150000 ( 0.156812)<br>
0.150000 0.000000 0.150000 ( 0.157045)<br>
0.150000 0.000000 0.150000 ( 0.156393)<br>
0.150000 0.000000 0.150000 ( 0.156002)<br>
0.150000 0.000000 0.150000 ( 0.159343)<br>
0.150000 0.010000 0.160000 ( 0.159755)<br>
0.150000 0.000000 0.150000 ( 0.158942)<br>
0.150000 0.000000 0.150000 ( 0.158270)<br>
0.150000 0.000000 0.150000 ( 0.158734)</p>
<p>== git clone git://bogomips.org/ruby.git ephemeral-class</p>
<p>ruby 1.9.3dev (2011-06-09 trunk 31961) [x86_64-linux]<br>
loop_eagain (read_nonblock)<br>
0.100000 0.000000 0.100000 ( 0.101462)<br>
0.080000 0.010000 0.090000 ( 0.100878)<br>
0.100000 0.000000 0.100000 ( 0.100596)<br>
0.100000 0.000000 0.100000 ( 0.101341)<br>
0.100000 0.000000 0.100000 ( 0.100753)<br>
0.100000 0.000000 0.100000 ( 0.099882)<br>
0.090000 0.000000 0.090000 ( 0.100205)<br>
0.100000 0.000000 0.100000 ( 0.099895)<br>
0.100000 0.000000 0.100000 ( 0.101218)<br>
0.090000 0.010000 0.100000 ( 0.100429)<br>
loop_wait_readable (Kgio::Socket#kgio_tryread)<br>
0.000000 0.010000 0.010000 ( 0.004570)<br>
0.010000 0.000000 0.010000 ( 0.005165)<br>
0.010000 0.000000 0.010000 ( 0.004236)<br>
0.000000 0.000000 0.000000 ( 0.004767)<br>
0.000000 0.000000 0.000000 ( 0.004186)<br>
0.000000 0.000000 0.000000 ( 0.004813)<br>
0.000000 0.000000 0.000000 ( 0.004186)<br>
0.000000 0.000000 0.000000 ( 0.004755)<br>
0.000000 0.000000 0.000000 ( 0.004168)<br>
0.000000 0.000000 0.000000 ( 0.004199)<br>
loop_wait_readable (Kgio::Pipe#kgio_tryread)<br>
0.000000 0.000000 0.000000 ( 0.005383)<br>
0.000000 0.000000 0.000000 ( 0.004787)<br>
0.010000 0.000000 0.010000 ( 0.005284)<br>
0.000000 0.000000 0.000000 ( 0.004784)<br>
0.010000 0.000000 0.010000 ( 0.005311)<br>
0.000000 0.000000 0.000000 ( 0.004770)<br>
0.010000 0.000000 0.010000 ( 0.005299)<br>
0.000000 0.000000 0.000000 ( 0.004811)<br>
0.000000 0.000000 0.000000 ( 0.005347)<br>
0.000000 0.000000 0.000000 ( 0.004770)</p>
<p>I added a separate set of tests for Kgio::Pipe vs Kgio::Socket since<br>
Kgio::Socket has a small, Linux-only optimization to avoid fcntl()<br>
syscalls entirely.</p>
<a name="script-I-used"></a>
<h1 >script I used:<a href="#script-I-used" class="wiki-anchor">¶</a></h1>
<a name="based-on-one-liner-by-Charles-Nutter-ruby-core36875"></a>
<h1 >based on one liner by Charles Nutter <a href="/issues/3905">[ruby-core:36875]</a><a href="#based-on-one-liner-by-Charles-Nutter-ruby-core36875" class="wiki-anchor">¶</a></h1>
<a name="reformatted-and-added-kgio-tests"></a>
<h1 >reformatted and added kgio tests<a href="#reformatted-and-added-kgio-tests" class="wiki-anchor">¶</a></h1>
<p>----------------------- 8< ------------------------<br>
require 'kgio'<br>
require 'benchmark'</p>
<p>def loop_eagain(sock)<br>
i = 0<br>
begin<br>
sock.read_nonblock(1)<br>
rescue Errno::EAGAIN<br>
return if i >= 10_000<br>
i += 1<br>
retry<br>
end<br>
end</p>
<p>def loop_wait_readable(sock)<br>
i = 0<br>
case sock.kgio_tryread(1)<br>
when :wait_readable<br>
return if i >= 10_000<br>
i += 1<br>
when String then break # success<br>
when nil then break # EOF<br>
end while true<br>
end</p>
<p>host = 'yhbt.net' # yhbt.net webmaster is OK with testing against it<br>
puts "loop_eagain (read_nonblock)"<br>
10.times {<br>
sock = TCPSocket.new(host, 80)<br>
puts Benchmark.measure { loop_eagain(sock) }<br>
}</p>
<p>puts "loop_wait_readable (Kgio::Socket#kgio_tryread)"<br>
addr = Socket.pack_sockaddr_in(80, host) # kgio doesn't do DNS lookups<br>
10.times {<br>
sock = Kgio::Socket.new(addr)<br>
puts Benchmark.measure { loop_wait_readable(sock) }<br>
}</p>
<h2>puts "loop_wait_readable (Kgio::Pipe#kgio_tryread)"<br>
addr = Socket.pack_sockaddr_in(80, host) # kgio doesn't do DNS lookups<br>
10.times {<br>
r, w = Kgio::Pipe.new<br>
puts Benchmark.measure { loop_wait_readable(r) }<br>
}<br>
------------------------- 8< ------------------------</h2>
<p>Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176502011-06-10T08:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>A better idea would be to get a kgio-like API into Ruby itself and<br>
encourage people to start using that. kgio itself will never take off<br>
since it's *nix-only and written in C, so it should be moved into Ruby<br>
and the Ruby spec itself if people really want it (without the ugly<br>
"kgio_" prefixes everywhere).</p>
</blockquote>
<p>I've started working on a "try" branch on top of Ruby trunk:<br>
<a href="http://bogomips.org/ruby.git?h=try" class="external">http://bogomips.org/ruby.git?h=try</a></p>
<p>I've only made one commit implementing IO#trywrite:<br>
<a href="http://bogomips.org/ruby.git/commit/?h=try&id=bd0d59fe162d0f1069df4cd3dc86a7a303c4930d" class="external">http://bogomips.org/ruby.git/commit/?h=try&id=bd0d59fe162d0f1069df4cd3dc86a7a303c4930d</a></p>
<p>If there's interest, I'll work on it more (and more frequently)<br>
or email patches/pull requests.</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176532011-06-10T10:53:06Zko1 (Koichi Sasada)
<ul></ul><p>Hi,</p>
<p>(2011/06/07 2:55), Eric Wong wrote:</p>
<blockquote>
<p>Akira Tanaka <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a> wrote:</p>
<blockquote>
<p>I don't against for the ephemeral class flag but<br>
it needs discussion with ko1 and/or matz.</p>
</blockquote>
<p>Can either of them comment please? I would really like to see<br>
this performance regression fixed in 1.9.3.</p>
</blockquote>
<p>Clearing method caching cause the following 2 overheads:</p>
<p>(1) Clearing overhead<br>
(2) Cache misses because of clearing methods</p>
<p>Which is your purpose?</p>
<p>For (1), I made an alternative patch:<br>
<a href="http://www.atdot.net/sp/readonly/x8wjml" class="external">http://www.atdot.net/sp/readonly/x8wjml</a></p>
<p>For (2), ephemeral class seems good.</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176542011-06-10T13:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>SASADA Koichi <a href="mailto:ko1@atdot.net" class="email">ko1@atdot.net</a> wrote:</p>
<blockquote>
<p>Clearing method caching cause the following 2 overheads:</p>
<p>(1) Clearing overhead<br>
(2) Cache misses because of clearing methods</p>
<p>Which is your purpose?</p>
</blockquote>
<p>I used oprofile last year and think I was measuring CPU time, so (1)...</p>
<blockquote>
<p>For (1), I made an alternative patch:<br>
<a href="http://www.atdot.net/sp/readonly/x8wjml" class="external">http://www.atdot.net/sp/readonly/x8wjml</a></p>
</blockquote>
<p>Awesome! It gives roughly the same performance as my ephemeral class<br>
patch in my measurement script below and less intrusive.</p>
<p>Thank you very much for your feedback.</p>
<blockquote>
<p>For (2), ephemeral class seems good.</p>
</blockquote>
<p>Your patch for (1) improves (2), too. However, I think cache miss<br>
is already a huge problem because cache-clearing is called during GC.</p>
<p>"perf -e cache-misses" reported the same results (~910 for either patch<br>
vs 1K on unpatched trunk) with a formatted version of the one-liner<br>
Charles posted earlier:</p>
<p>---------------------- 8< ----------------------<br>
require 'benchmark'<br>
require 'socket'</p>
<p>def loop_eagain(sock)<br>
i = 0<br>
begin<br>
sock.read_nonblock(1)<br>
rescue Errno::EAGAIN<br>
return if i >= 10_000<br>
i += 1<br>
retry<br>
end<br>
end</p>
<h2>host = 'yhbt.net' # yhbt.net webmaster is OK with testing against it<br>
10.times {<br>
sock = TCPSocket.new(host, 80)<br>
puts Benchmark.measure { loop_eagain(sock) }<br>
}</h2>
<p>Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176562011-06-10T16:53:07Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>On Thu, Jun 9, 2011 at 3:17 AM, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>Nevermind, I misread the first time and got ordering of your question<br>
mixed up in my mind.</p>
<p>Once a class is tagged RCLASS_EPHEMERAL, it's impossible for it to<br>
write to the cache. There's no need to flush the cache for ephemeral<br>
classes because...<br>
...<br>
...the the /only/ safe way to use RCLASS_EPHEMERAL is before any methods<br>
are called (and cached) for the singleton class.</p>
</blockquote>
<blockquote>
<blockquote>
<p>begin<br>
io.read_nonblock<br>
rescue WaitReadable => e<br>
class << self<br>
# add something cute</p>
</blockquote>
<p>Any methods defined here will never be cached, because RCLASS_EPHEMERAL<br>
was set before we re-entered Ruby-land.</p>
</blockquote>
<p>Ok, not being familiar with the MRI code, and not seeing more than a<br>
few lines of context in the patch, I didn't get this.</p>
<p>So summarizing in non-code:</p>
<ul>
<li>Ephemeral class creation does not flush global cache</li>
<li>...because ephemeral class methods will never be cached</li>
</ul>
<p>But I'm confused; if code has already cached a method from an<br>
ephemeral class's superclass, and someone adds to the ephemeral class,<br>
does the new method get picked up? Hopefully adding methods to an<br>
ephemeral class still clears cache, because otherwise invocation won't<br>
see such changes. Am I following?</p>
<p>I need to look at ko1's patch since that seems to please you.</p>
<ul>
<li>Charlie</li>
</ul> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176572011-06-10T16:53:07Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>On Thu, Jun 9, 2011 at 3:52 AM, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>Since you provided the benchmark code, I reformatted and<br>
made a version of it for kgio (see below).</p>
<p>Summary: ephemeral-class performance noticeably (and will have<br>
a bigger impact for bigger applications, not small benchmark scripts)</p>
<p>kgio reduces overhead greatly by avoiding exceptions. Real-world<br>
results (see the dalli README) are less impressive, of course, but still<br>
noticeable.</p>
</blockquote>
<p>Yeah, I'm not surprised by these numbers. In JRuby the cost of EAGAIN<br>
was so great I had to turn off having it generate backtraces;<br>
exception backtraces are much more expensive on JVM (and by extension<br>
JRuby) so flow control based on exception-handling is absolutely<br>
terrible. Only by making EAGAIN backtrace-free could I get reasonable<br>
perf. I'd prefer no exception at all for errnos that are nonfatal.</p>
<p>I will have to try doing something like your ephemeral patch in JRuby.<br>
For us, extending does not flush the global cache, but still has the<br>
cost of creating the singleton class. Not free, but not too bad.</p>
<ul>
<li>Charlie</li>
</ul> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176592011-06-10T18:53:07Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Charles Oliver Nutter <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>On Thu, Jun 9, 2011 at 3:17 AM, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<p>Nevermind, I misread the first time and got ordering of your question<br>
mixed up in my mind.</p>
<p>Once a class is tagged RCLASS_EPHEMERAL, it's impossible for it to<br>
write to the cache. There's no need to flush the cache for ephemeral<br>
classes because...<br>
...<br>
...the the /only/ safe way to use RCLASS_EPHEMERAL is before any methods<br>
are called (and cached) for the singleton class.</p>
</blockquote>
<blockquote>
<blockquote>
<p>begin<br>
io.read_nonblock<br>
rescue WaitReadable => e<br>
class << self<br>
# add something cute</p>
</blockquote>
<p>Any methods defined here will never be cached, because RCLASS_EPHEMERAL<br>
was set before we re-entered Ruby-land.</p>
</blockquote>
<p>Ok, not being familiar with the MRI code, and not seeing more than a<br>
few lines of context in the patch, I didn't get this.</p>
<p>So summarizing in non-code:</p>
<ul>
<li>Ephemeral class creation does not flush global cache</li>
<li>...because ephemeral class methods will never be cached</li>
</ul>
</blockquote>
<p>Yes, to both. Creation of new classes (ephemeral or not) never touches<br>
the method cache, only destruction clears the cache. The global method<br>
cache includes the (exact) class of each method along with the method<br>
ID.</p>
<blockquote>
<p>But I'm confused; if code has already cached a method from an<br>
ephemeral class's superclass, and someone adds to the ephemeral class,<br>
does the new method get picked up? Hopefully adding methods to an<br>
ephemeral class still clears cache, because otherwise invocation won't<br>
see such changes. Am I following?</p>
</blockquote>
<p>Yes a method gets picked up in the ephmeral class if the (non-ephemeral)<br>
superclass is modified.</p>
<p>The MRI method cache relies on the class of the calling object matching<br>
/exactly/ with the class of the cached method for a hit. Modifying a<br>
superclass of any class</p>
<p>I think adding any method anywhere will clear the cache in MRI. But<br>
it's not needed for adding methods to ephemeral classes since they'd<br>
never have any methods in the cache in the first place.</p>
<blockquote>
<p>I need to look at ko1's patch since that seems to please you.</p>
</blockquote>
<p>Yes, it's the best patch (along with r28813) I've seen for this issue.<br>
Easy to understand, too.</p>
<p>The only thing I can imagine being better is to make uncached method<br>
lookup fast enough to where the cache becomes obsolete. I think that<br>
would be difficult, though.</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176602011-06-10T18:53:07Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<blockquote>
<p>For (1), I made an alternative patch:<br>
<a href="http://www.atdot.net/sp/readonly/x8wjml" class="external">http://www.atdot.net/sp/readonly/x8wjml</a></p>
</blockquote>
<p>Awesome! It gives roughly the same performance as my ephemeral class<br>
patch in my measurement script below and less intrusive.</p>
</blockquote>
<p>One possible issue is the VM state counter overflowing. Maybe we should<br>
empty the method cache on the rare event of a VM state counter overflow<br>
to avoid false positives?</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176612011-06-10T18:59:06Zko1 (Koichi Sasada)
<ul></ul><p>Hi,</p>
<p>(2011/06/10 13:10), Eric Wong wrote:</p>
<blockquote>
<blockquote>
<p>For (2), ephemeral class seems good.</p>
</blockquote>
<p>Your patch for (1) improves (2), too. However, I think cache miss<br>
is already a huge problem because cache-clearing is called during GC.</p>
</blockquote>
<p>My patch reduces "clearing method cache" time. And because of my patch<br>
clears all cache entries, method cache misses should be increase (in<br>
other words, it is not a solution for (2)).</p>
<p>I will solve this problem with other techniques.</p>
<p>First of all, can I commit my patch?</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176632011-06-10T19:23:06Zko1 (Koichi Sasada)
<ul></ul><p>(2011/06/10 18:50), Eric Wong wrote:</p>
<blockquote>
<p>One possible issue is the VM state counter overflowing. Maybe we should<br>
empty the method cache on the rare event of a VM state counter overflow<br>
to avoid false positives?</p>
</blockquote>
<p>Good point. We need to care overflow. However, current MRI lacks this<br>
process.</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=176832011-06-11T03:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>SASADA Koichi <a href="mailto:ko1@atdot.net" class="email">ko1@atdot.net</a> wrote:</p>
<blockquote>
<p>(2011/06/10 13:10), Eric Wong wrote:</p>
<blockquote>
<blockquote>
<p>For (2), ephemeral class seems good.</p>
</blockquote>
<p>Your patch for (1) improves (2), too. However, I think cache miss<br>
is already a huge problem because cache-clearing is called during GC.</p>
</blockquote>
<p>My patch reduces "clearing method cache" time. And because of my patch<br>
clears all cache entries, method cache misses should be increase (in<br>
other words, it is not a solution for (2)).</p>
</blockquote>
<p>Oh, I thought you meant CPU cache misses. Method cache miss shouldn't<br>
be a problem at all because the class is GC'ed.</p>
<blockquote>
<p>I will solve this problem with other techniques.</p>
<p>First of all, can I commit my patch?</p>
</blockquote>
<p>Please do (with workaround for overflow). Thank you!</p>
<p>--<br>
Eric Wong</p> Ruby master - Feature #3905: rb_clear_cache_by_class() called often during GC for non-blocking I/Ohttps://redmine.ruby-lang.org/issues/3905?journal_id=178492011-06-12T17:53:16Zko1 (Koichi Sasada)
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>This issue was solved with changeset r32024.<br>
Eric, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<hr>
<ul>
<li>vm_method.c (rb_clear_cache*): update only vm state version.</li>
<li>vm_method.c (rb_method_entry_get_without_cache, rb_method_entry):<br>
Fill method cache entry with vm state version, and<br>
check current vm state version for method (cache) look up.<br>
This modification speed-up invaridating of global method cache table.<br>
[Ruby 1.9 - Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: rb_clear_cache_by_class() called often during GC for non-blocking I/O (Closed)" href="https://redmine.ruby-lang.org/issues/3905">#3905</a>] <a href="/issues/3905">[ruby-core:36908]</a></li>
</ul>