summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-06 02:15:05 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-06 02:15:05 +0000
commitfcf8c622fd3d4e288c40205bd0f745eeb5844705 (patch)
tree5c8725e44f472c5698ab71d719f241918227237a
parent24aa7a13ca0e7dacc18c705bbbe54fe4bcf23337 (diff)
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--thread.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/thread.c b/thread.c
index ae80a70682..360807b073 100644
--- a/thread.c
+++ b/thread.c
@@ -3971,12 +3971,13 @@ ruby_ppoll(struct pollfd *fds, nfds_t nfds,
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);
}