Before this patch, the MN scheduler waits for the IO with the
following steps:
poll(fd, timeout=0) to check fd is ready or not.
if fd is not ready, waits with MN thread scheduler
call func to issue the blocking I/O call
The advantage of advanced poll() is we can wait for the
IO ready for any fds. However poll() becomes overhead
for already ready fds.
This patch changes the steps like:
call func to issue the blocking I/O call
if the func returns EWOULDBLOCK the fd is O_NONBLOCK
and we need to wait for fd is ready so that waits with MN
thread scheduler.
In this case, we can wait only for O_NONBLOCK fds. Otherwise
it waits with blocking operations such as read() system call.
However we don't need to call poll() to check fd is ready
in advance.
With this patch we can observe performance improvement
on microbenchmark which repeats blocking I/O (not O_NONBLOCK fd) with and without MN thread scheduler.
require'benchmark'f=open('/dev/null','w')f.sync=trueTN=1N=1_000_000/TNBenchmark.bm{|x|x.report{TN.times.map{Thread.new{N.times{f.print'.'}}}.each(&:join)}}__END__
TN = 1
user system total real
ruby32 0.393966 0.101122 0.495088 ( 0.495235)
ruby33 0.493963 0.089521 0.583484 ( 0.584091)
ruby33+MN 0.639333 0.200843 0.840176 ( 0.840291) <- Slow
this+MN 0.512231 0.099091 0.611322 ( 0.611074) <- Good
Do not
poll
firstBefore this patch, the MN scheduler waits for the IO with the
following steps:
poll(fd, timeout=0)
to check fd is ready or not.func
to issue the blocking I/O callThe advantage of advanced
poll()
is we can wait for theIO ready for any fds. However
poll()
becomes overheadfor already ready fds.
This patch changes the steps like:
func
to issue the blocking I/O callfunc
returnsEWOULDBLOCK
the fd isO_NONBLOCK
and we need to wait for fd is ready so that waits with MN
thread scheduler.
In this case, we can wait only for
O_NONBLOCK
fds. Otherwiseit waits with blocking operations such as
read()
system call.However we don't need to call
poll()
to check fd is readyin advance.
With this patch we can observe performance improvement
on microbenchmark which repeats blocking I/O (not
O_NONBLOCK
fd) with and without MN thread scheduler.