ruby-changes:51655
From: normal <ko1@a...>
Date: Fri, 6 Jul 2018 11:15:08 +0900 (JST)
Subject: [ruby-changes:51655] normal:r63867 (trunk): thread.c (ruby_ppoll): improve timespec to msec conversion
normal 2018-07-06 11:15:05 +0900 (Fri, 06 Jul 2018) New Revision: 63867 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63867 Log: thread.c (ruby_ppoll): improve timespec to msec conversion Round up non-zero <1ms timeouts to 1ms and use INT_MAX instead of infinite (-1) for extremely large timeouts. All of our ppoll/select callers are able to handle spurious wakeups, anyways. This avoids excessive CPU usage and busy waits with short timeouts to rb_wait_for_single_fd. CPU usage with the following script is significantly reduced for systems with "#undef HAVE_PPOLL": require 'io/wait' r, w = IO.pipe Thread.new { loop { r.wait_readable(0.000001) } }.join(5) exit!(0) Low-resolution in poll(2) still sucks, though... Note: I don't see the value in making a similar change to time_timeval of a <1us sleep is attempted because of GVL release and syscall latency. Modified files: trunk/thread.c Index: thread.c =================================================================== --- thread.c (revision 63866) +++ thread.c (revision 63867) @@ -3971,12 +3971,13 @@ ruby_ppoll(struct pollfd *fds, nfds_t nf https://github.com/ruby/ruby/blob/trunk/thread.c#L3971 int tmp, tmp2; if (ts->tv_sec > INT_MAX/1000) - timeout_ms = -1; + timeout_ms = INT_MAX; else { tmp = (int)(ts->tv_sec * 1000); - tmp2 = (int)(ts->tv_nsec / (1000 * 1000)); + /* round up 1ns to 1ms to avoid excessive wakeups for <1ms sleep */ + tmp2 = (int)((ts->tv_nsec + 999999L) / (1000L * 1000L)); if (INT_MAX - tmp < tmp2) - timeout_ms = -1; + timeout_ms = INT_MAX; else timeout_ms = (int)(tmp + tmp2); } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/