Yehuda Katz <wycats / gmail.com> wrote:
> Bug #5138: Add nonblocking IO that does not use exceptions for EOF and EWOULDBLOCK

I don't want this issue to get dropped, so I'm summarizing the
discussion so far for the benefit of folks who haven't followed
everything (including discussions in related threads to this one).

* readpartial + IO.select can still block indefinitely due to:

  - user space layers and buffering (SSL, gzip/zlib)

  - spurious wakeup on some socket types/kernels

* Exceptions with the current *_nonblock methods are expensive.

  - extending with IO::Wait* increments the global VM state version

    * This invalidates both the global method cache and inline caches in
      1.9.3.  Invaliding the caches is itself an inexpensive operation
      since 1.9.3, but the cost of subsequent cache misses can hurt[1]

    * This can overflow VM state version within a couple of hours/days
      on 32-bit systems if IO::Wait* exceptions are raised constantly.
      Overflowing state version may trigger very rare bugs with
      false-positive cache hits; vm_clear_all_inline_method_cache() is
      currently unimplemented to deal with this situation.
      Overflow is not likely to ever be a problem on 64-bit.

  - backtrace generation cost

    * Generating backtrace is more expensive in MRI 1.9/2.x than MRI 1.8,
      it might be even more expensive in alternative VMs

    * Additional garbage overhead from backtrace strings

* IO::Wait*/Errno::EAGAIN are very common exceptions.

  - Anybody using *_nonblock will need to care for exceptions with a
    begin/rescue.  Changing begin/rescue into the equivalent
    case statement requires roughly the same amount of code.

  - These exceptions make $DEBUG unnecessarily noisy


[1] - I haven't done extensive benchmarking on method cache/inline cache
      effectiveness in MRI.  More experienced MRI developers should know
      more about this topic than I do.