[#25936] [Bug:1.9] [rubygems] $LOAD_PATH includes bin directory — Nobuyoshi Nakada <nobu@...>

Hi,

10 messages 2009/10/05

[#25943] Disabling tainting — Tony Arcieri <tony@...>

Would it make sense to have a flag passed to the interpreter on startup that

16 messages 2009/10/05

[#26028] [Bug #2189] Math.atanh(1) & Math.atanh(-1) should not raise an error — Marc-Andre Lafortune <redmine@...>

Bug #2189: Math.atanh(1) & Math.atanh(-1) should not raise an error

14 messages 2009/10/10

[#26222] [Bug #2250] IO::for_fd() objects' finalization dangerously closes underlying fds — Mike Pomraning <redmine@...>

Bug #2250: IO::for_fd() objects' finalization dangerously closes underlying fds

11 messages 2009/10/22

[#26244] [Bug #2258] Kernel#require inside rb_require() inside rb_protect() inside SysV context fails — Suraj Kurapati <redmine@...>

Bug #2258: Kernel#require inside rb_require() inside rb_protect() inside SysV context fails

24 messages 2009/10/22

[#26361] [Feature #2294] [PATCH] ruby_bind_stack() to embed Ruby in coroutine — Suraj Kurapati <redmine@...>

Feature #2294: [PATCH] ruby_bind_stack() to embed Ruby in coroutine

42 messages 2009/10/27

[#26371] [Bug #2295] segmentation faults — tomer doron <redmine@...>

Bug #2295: segmentation faults

16 messages 2009/10/27

[ruby-core:26174] Re: A challenge: Enumerator#next in JRuby

From: Charles Oliver Nutter <headius@...>
Date: 2009-10-19 23:10:23 UTC
List: ruby-core #26174
On Sat, Oct 17, 2009 at 3:31 PM, Charles Oliver Nutter
<headius@headius.com> wrote:
> I am also starting to suspect that a protocol like Akira's may be the
> *ONLY* way to reliably implement external enumeration on runtimes that
> don't provide coroutines and that do not allow non-rooting threads. I
> also suspect there may be object reference issues even on MRI, since
> marking a thread as non-rooting is a very coarse-grained solution,
> especially if objects are created only in the enumerating thread/fiber
> and you want them to stay alive.
>
> Bottom line once again: It may not be possible to support
> Enumerator#next without requiring a lightweight enumerator protocol in
> JRuby.

More updates...

I have managed to get threaded iteration working, with the threads
dying when the enumerator is collected, but it's extremely touchy. If
you spin up enumerators at a rate greater than about 10 per second it
will not be able to GC and clean up threads fast enough to prevent
hitting the per-process thread limit. This could probably be sped up a
bit using a Java finalizer instead of a Ruby finalizer, but it's never
going to be great. Arbitrary external enumeration is looking bad at
this point.

To start trying to mitigate this, I've implemented part of a
lightweight iterator protocol to test in JRuby. It works for the
"each" variants in Array and Hash, and we'll be trying to add others
to support various other "enumeratorized" core class methods. It's
likely we will only ship with the iterator protocol plus as many
core-class impls of it as possible and *no* external enumeration in
other cases.

I ran some benchmarks as well... JRuby's threaded enumerators spin up
5-20x times slower than 1.9's, but nowhere near as slow as 1.8.7.
1.8.7 seems to be broken it's so bad, and it shoots up to 400-500MB
during this benchmark:

First JRuby with lightweight enumerators:

~/projects/jruby =E2=9E=94 (pickjdk 4 ; jruby -rbenchmark -e "10.times {put=
s
Benchmark.measure {10_000.times {|i| e =3D [1,2,3].each; e.next; e.next;
e.next }}}")
New JDK: 1.6.0
  1.550000   0.000000   1.550000 (  1.461000)
  0.768000   0.000000   0.768000 (  0.768000)
  0.093000   0.000000   0.093000 (  0.093000)
  0.084000   0.000000   0.084000 (  0.084000)
  0.085000   0.000000   0.085000 (  0.085000)
  0.088000   0.000000   0.088000 (  0.088000)
  0.080000   0.000000   0.080000 (  0.080000)
  0.083000   0.000000   0.083000 (  0.083000)
  0.080000   0.000000   0.080000 (  0.081000)
  0.079000   0.000000   0.079000 (  0.079000)

JRuby with threaded enumerators:

~/projects/jruby =E2=9E=94 (pickjdk 4 ; jruby -rbenchmark -e "10.times {put=
s
Benchmark.measure {10_000.times {|i| e =3D '123'.each_byte; e.next;
e.next; e.next }}}")
New JDK: 1.6.0
  5.424000   0.000000   5.424000 (  5.296000)
  3.455000   0.000000   3.455000 (  3.454000)
  2.350000   0.000000   2.350000 (  2.350000)
  2.485000   0.000000   2.485000 (  2.485000)
  2.082000   0.000000   2.082000 (  2.082000)
  2.295000   0.000000   2.295000 (  2.295000)
  2.061000   0.000000   2.061000 (  2.061000)
  2.162000   0.000000   2.162000 (  2.162000)
  2.139000   0.000000   2.139000 (  2.139000)
  2.288000   0.000000   2.288000 (  2.288000)

JRuby with threaded enumerators and an internal native thread pool:

~/projects/jruby =E2=9E=94 (pickjdk 4 ; jruby
-J-Djruby.thread.pool.enabled=3Dtrue -rbenchmark -e "10.times {puts
Benchmark.measure {10_000.times {|i| e =3D '123'.each_byte; e.next;
e.next; e.next }}}")
New JDK: 1.6.0
  4.020000   0.000000   4.020000 (  3.971000)
  2.939000   0.000000   2.939000 (  2.939000)
  1.689000   0.000000   1.689000 (  1.689000)
  1.572000   0.000000   1.572000 (  1.572000)
  1.721000   0.000000   1.721000 (  1.721000)
  1.247000   0.000000   1.247000 (  1.247000)
  1.195000   0.000000   1.195000 (  1.195000)
  1.494000   0.000000   1.494000 (  1.494000)
  1.358000   0.000000   1.358000 (  1.358000)
  1.192000   0.000000   1.192000 (  1.192000)

Ruby 1.8.7 trunk, as far as I cared to run it:

~/projects/jruby =E2=9E=94 ruby1.8.7 -rbenchmark -e "10.times {puts
Benchmark.measure {10_000.times {|i| e =3D [1,2,3].each; e.next; e.next;
e.next }}}"
 13.560000  18.530000  32.090000 ( 36.192230)
 36.080000  63.300000  99.380000 (115.481131)
^C

Ruby 1.9 from this summer (preview 1 or something):

~/projects/jruby =E2=9E=94 ruby1.9 -rbenchmark -e "10.times {puts
Benchmark.measure {10_000.times {|i| e =3D [1,2,3].each; e.next; e.next;
e.next }}}"
  0.170000   0.120000   0.290000 (  0.308234)
  0.170000   0.120000   0.290000 (  0.306141)
  0.180000   0.130000   0.310000 (  0.304755)
  0.170000   0.120000   0.290000 (  0.309701)
  0.180000   0.120000   0.300000 (  0.317838)
  0.180000   0.130000   0.310000 (  0.303773)
  0.170000   0.130000   0.300000 (  0.315374)
  0.170000   0.130000   0.300000 (  0.315610)
  0.170000   0.120000   0.290000 (  0.304459)
  0.170000   0.120000   0.290000 (  0.304576)

Most of this work is contained in
lib/ruby/site_ruby/shared/generator.rb on the "enumerator" branch of
JRuby's git repository here: git://kenai.com/jruby~main

Comments and discussion are welcome. Enumerator#next is an extremely
problematic feature to support across impls.

- Charlie

In This Thread