mirror of
https://github.com/ruby/ruby.git
synced 2025-09-17 01:23:57 +02:00
Do not poll
first
Before this patch, the MN scheduler waits for the IO with the following steps: 1. `poll(fd, timeout=0)` to check fd is ready or not. 2. if fd is not ready, waits with MN thread scheduler 3. 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: 1. call `func` to issue the blocking I/O call 2. 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. ```ruby require 'benchmark' f = open('/dev/null', 'w') f.sync = true TN = 1 N = 1_000_000 / TN Benchmark.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 ```
This commit is contained in:
parent
6c252912af
commit
d65d2fb6b5
5 changed files with 80 additions and 46 deletions
5
io.c
5
io.c
|
@ -1146,6 +1146,11 @@ static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval
|
|||
static inline int
|
||||
io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct timeval *timeout)
|
||||
{
|
||||
if (!timeout && rb_thread_mn_schedulable(thread)) {
|
||||
RUBY_ASSERT(errno == EWOULDBLOCK || errno == EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ready = nogvl_wait_for(thread, fptr, events, timeout);
|
||||
|
||||
if (ready > 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue