On Wed, Jun 8, 2011 at 4:00 PM, Eric Wong <normalperson / yhbt.net> wrote:
> Charles Nutter <headius / headius.com> wrote:
>> 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?
>
> No, it's a situation where the user must be careful and not shoot
> themselves in the foot. It is C, after all.

But isn't this an exception object that will be raised into Ruby code?
In other words...

begin
  io.read_nonblock
rescue WaitReadable => e
  class << self
    # add something cute
  end
end

>> 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?
>
> This would break code already written for Ruby 1.9.2. Otherwise, I
> would love to do it (not that I have the power to actually do it).
>
> I absolutely *HATE* the way Ruby extends classes and throws exceptions
> for EAGAIN, but there's not much one can do about it.

Ok, I'm glad we agree here :) In fact, here's the code that extends
WaitReadable in JRuby:

// FIXME: *oif* 1.9 actually does this
if (ruby.is1_9()) {
    eagain.getException().extend(new IRubyObject[]
{ruby.getIO().getConstant("WaitReadable")});
}

Perhaps I should also express my disapproval through song?

> A better idea would be to get a kgio-like API into Ruby itself and
> encourage people to start using that. kgio itself will never take off
> since it's *nix-only and written in C, so it should be moved into Ruby
> and the Ruby spec itself if people really want it (without the ugly
> "kgio_" prefixes everywhere).

At least on the JRuby side of things, I'd love to build this in as a
shipping (but nonstandard) library. Java's NIO has similar goals in
mind...specifically, if you need to try again on a nonblocking read,
it just returns a boolean rather than raising some big heavy error. In
fact, kgio may map very well to NIO, at least for the common cases.

Interested in the overhead of this EAGAIN nonsense, I ran a quick
benchmark. I include it here for the amusement of all. It demonstrates
pretty clearly the impact of the extend(WaitReadable), since that's
really the only thing that differs between the two (at least in
JRuby).

~/projects/jruby  ruby -v -rbenchmark -rsocket -e "def
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {
loop_eagain(sock) } }
"
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
  0.110000   0.020000   0.130000 (  0.130989)
  0.110000   0.020000   0.130000 (  0.128334)
  0.110000   0.020000   0.130000 (  0.135947)
  0.110000   0.020000   0.130000 (  0.131490)
  0.110000   0.020000   0.130000 (  0.131814)
  0.110000   0.020000   0.130000 (  0.132031)
  0.110000   0.020000   0.130000 (  0.129517)
  0.110000   0.020000   0.130000 (  0.128233)
  0.110000   0.020000   0.130000 (  0.128804)
  0.110000   0.020000   0.130000 (  0.127877)

~/projects/jruby  ruby1.9 -v -rbenchmark -rsocket -e "def
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {
loop_eagain(sock) } }
"
ruby 1.9.2p160 (2011-01-16 revision 30579) [x86_64-darwin10.6.0]
  0.260000   0.030000   0.290000 (  0.287646)
  0.280000   0.030000   0.310000 (  0.315121)
  0.260000   0.020000   0.280000 (  0.288908)
  0.270000   0.030000   0.300000 (  0.291922)
  0.260000   0.020000   0.280000 (  0.292273)
  0.270000   0.020000   0.290000 (  0.301361)
  0.260000   0.030000   0.290000 (  0.291552)
  0.270000   0.020000   0.290000 (  0.298062)
  0.270000   0.030000   0.300000 (  0.337271)
  0.280000   0.040000   0.320000 (  0.348292)

~/projects/jruby  jruby -v -rbenchmark -rsocket -e "def
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {
loop_eagain(sock) } }
"
jruby 1.7.0.dev (ruby-1.8.7-p330) (2011-06-08 c1029d9) (Java
HotSpot(TM) 64-Bit Server VM 1.6.0_22) [darwin-x86_64-java]
  1.102000   0.000000   1.102000 (  1.051000)
  0.583000   0.000000   0.583000 (  0.583000)
  0.607000   0.000000   0.607000 (  0.607000)
  0.120000   0.000000   0.120000 (  0.120000)
  0.119000   0.000000   0.119000 (  0.119000)
  0.123000   0.000000   0.123000 (  0.123000)
  0.113000   0.000000   0.113000 (  0.113000)
  0.120000   0.000000   0.120000 (  0.120000)
  0.124000   0.000000   0.124000 (  0.124000)
  0.117000   0.000000   0.117000 (  0.117000)

~/projects/jruby  jruby --1.9 -v -rbenchmark -rsocket -e "def
loop_eagain(sock); i = 0; begin; sock.read_nonblock(1); rescue
Errno::EAGAIN; return if i >= 10_000; i+= 1; retry; end; end; 10.times
{ sock = TCPSocket.new('google.com', 80); puts Benchmark.measure {
loop_eagain(sock) } }
"
jruby 1.7.0.dev (ruby-1.9.2-p136) (2011-06-08 c1029d9) (Java
HotSpot(TM) 64-Bit Server VM 1.6.0_22) [darwin-x86_64-java]
  1.965000   0.000000   1.965000 (  1.964000)
  1.369000   0.000000   1.369000 (  1.369000)
  0.712000   0.000000   0.712000 (  0.712000)
  0.567000   0.000000   0.567000 (  0.566000)
  0.208000   0.000000   0.208000 (  0.208000)
  0.209000   0.000000   0.209000 (  0.209000)
  0.204000   0.000000   0.204000 (  0.204000)
  0.207000   0.000000   0.207000 (  0.207000)
  0.207000   0.000000   0.207000 (  0.206000)
  0.213000   0.000000   0.213000 (  0.212000)

- Charlie