From: "mame (Yusuke Endoh)" Date: 2012-11-24T13:51:49+09:00 Subject: [ruby-core:50011] [ruby-trunk - Feature #6154] Eliminate extending WaitReadable/Writable at runtime Issue #6154 has been updated by mame (Yusuke Endoh). Target version set to next minor I postpone this ticket to next minor. Very sorry. If Eric Wong were a committer, I would leave this to him. -- Yusuke Endoh ---------------------------------------- Feature #6154: Eliminate extending WaitReadable/Writable at runtime https://bugs.ruby-lang.org/issues/6154#change-33785 Author: headius (Charles Nutter) Status: Assigned Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: Target version: next minor The nonblocking IO operations started extending WaitReadable or WaitWritable into the Errno::EAGAIN instance some time during the 1.9 series. This has a rather high cost, since a singleton class must be created and the global method cache must be flushed. The attached patch instead creates two new classes of the following form, and raises them rather than raising a singleton EAGAIN: class IO::EAGAINReadable < Errno::EAGAIN include WaitReadable end class IO::EAGAINWritable < Errno::EAGAIN include WaitWritable end The performance of repeatedly doing unsuccessful nonblocking reads improves by about 20%: BEFORE: system ~/projects/ruby $ ./ruby2.0.0 -rbenchmark -rsocket -e "sock = TCPSocket.new('localhost', 22); 10.times { puts Benchmark.measure { 100_000.times { begin; sock.read_nonblock(10); rescue IO::WaitReadable; end } } }" 1.210000 0.110000 1.320000 ( 1.328921) 1.220000 0.120000 1.340000 ( 1.326136) 1.220000 0.110000 1.330000 ( 1.334026) 1.230000 0.110000 1.340000 ( 1.349927) 1.310000 0.130000 1.440000 ( 1.426608) 1.210000 0.110000 1.320000 ( 1.333530) 1.220000 0.120000 1.340000 ( 1.330352) 1.230000 0.110000 1.340000 ( 1.350455) 1.220000 0.120000 1.340000 ( 1.327550) 1.220000 0.110000 1.330000 ( 1.337785) AFTER: system ~/projects/ruby $ ./ruby2.0.0 -rbenchmark -rsocket -e "sock = TCPSocket.new('localhost', 22); 10.times { puts Benchmark.measure { 100_000.times { begin; sock.read_nonblock(10); rescue IO::WaitReadable; end } } }" 0.980000 0.110000 1.090000 ( 1.092166) 1.010000 0.120000 1.130000 ( 1.129877) 1.090000 0.120000 1.210000 ( 1.202066) 0.960000 0.110000 1.070000 ( 1.076274) 0.970000 0.100000 1.070000 ( 1.078000) 0.970000 0.110000 1.080000 ( 1.078156) 0.970000 0.110000 1.080000 ( 1.078005) 0.970000 0.110000 1.080000 ( 1.078266) 0.980000 0.110000 1.090000 ( 1.093039) 1.000000 0.110000 1.110000 ( 1.112519) This benchmark does not show the hidden cost of constantly invalidating the global method cache. I also modified a similar case in OpenSSL, where it previously created an SSLError and extended WaitReadable into it. -- http://bugs.ruby-lang.org/