aboutsummaryrefslogtreecommitdiffstats
path: root/rjit_c.rb
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2023-12-29 03:52:45 +0900
committerKoichi Sasada <ko1@atdot.net>2024-01-05 05:51:25 +0900
commitd65d2fb6b5c56c495f2f98f8e6ac5994ad5d93dd (patch)
tree3bf8410052a24b8da27cafe6f39ac13188a56ce1 /rjit_c.rb
parent6c252912af4981f016a9abdb4c1689307a4f1d2f (diff)
downloadruby-d65d2fb6b5c56c495f2f98f8e6ac5994ad5d93dd.tar.gz
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 ```
Diffstat (limited to 'rjit_c.rb')
-rw-r--r--rjit_c.rb1
1 files changed, 1 insertions, 0 deletions
diff --git a/rjit_c.rb b/rjit_c.rb
index f100fb911c..61ae3b04a7 100644
--- a/rjit_c.rb
+++ b/rjit_c.rb
@@ -1497,6 +1497,7 @@ module RubyVM::RJIT # :nodoc: all
nt: [CType::Pointer.new { self.rb_native_thread }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), nt)")],
ec: [CType::Pointer.new { self.rb_execution_context_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), ec)")],
sched: [self.rb_thread_sched_item, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), sched)")],
+ mn_schedulable: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), mn_schedulable)")],
serial: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), serial)")],
last_status: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), last_status)")],
calling: [CType::Pointer.new { self.rb_calling_info }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), calling)")],