Rubyのaccept_nonblock(exception: false)
Rubyのサーバーソケットのaccept_nonblock
は、IO
のread_nonblock
と同様にexception: false
でIO::WaitReadable
を投げないようにできる。
例外を投げる場合と投げない場合で、どれくらい差があるものなのか実験してみた。
require 'benchmark' require 'socket' class Integer def to_comma to_s.reverse.scan(/\d\d?\d?/).join(',').reverse end end repeat_num = Integer(ARGV.shift || '1_000_000') puts "repeat: #{repeat_num.to_comma}" s = TCPServer.new(0) Benchmark.bm(35) do |x| x.report('accept_nonblock') do repeat_num.times do begin s.accept_nonblock rescue IO::WaitReadable, Errno::EINTR # nothing to do. end end end x.report('accept_nonblock(exception: false)') do repeat_num.times do begin if (r = s.accept_nonblock(exception: false)) then if (r != :wait_readable) then r end end rescue Errno::EINTR # `exception: false'で捕捉されるのは # EAGAIN/EWOULDBLOCK,ECONNABORTE,EPROTOだけなので、例外EINTRの # 捕捉は必要。 end end end end
結果:
$ ./benchmark_socket_accept_nonblock.rb repeat: 1,000,000 user system total real accept_nonblock 20.477151 7.877416 28.354567 ( 29.273192) accept_nonblock(exception: false) 2.606960 6.471008 9.077968 ( 9.108173)
exception: false
の方が3倍速い。
しかし差がつくのはそもそも接続が来ないときなんだよな。
使ったほうがよいのかどうか迷う。