7

I'm seeing a lot of usages of sleep 0 in my one of my client project.

The code look something like this.

while true 
  ...
  ...
  sleep 0
end

Reading through some of the answer of SO like this it seems that sleep 0 has some significance.

What I want to known now is that does scheduling for other thread to run (if they are waiting to run) during the time slice 0 is a job of a lang VM like ruby or python or it is a job of kernel.

In order word does Ruby VM would honor sleep 0 like it is mention in the above link.

Community
  • 1
  • 1
Noobie
  • 461
  • 1
  • 12
  • 34

1 Answers1

9

Yes, for a couple of reasons, first of all, (mri) ruby threads are wrappers around native threads with an additional GVL lock.

Essentially what ruby is doing when you call sleep is calling the underlying, native, platform dependent sleep and releasing the GVL so that other running threads can acquire it. So sleep(0) is both yielding to other native threads that may be waiting to be executed as well as releasing the current thread's hold on the GVL which would otherwise keep the Ruby VM from executing.

Here's a quick rundown of how you can see this from mri source:

  1. We get the definition of Kernel sleep from https://github.com/ruby/ruby/blob/trunk/process.c#L7542, which we see is implemented in c in the function rb_f_sleep
  2. Next we go to rb_f_sleep and see that in the case of a single argument it calls rb_thread_wait_for
  3. Going to the rb_thread_wait_for definition we see a call to sleep_timeval
  4. sleep_timeval has a call to native_sleep
  5. native_sleep is platform dependent and implemented in thread_pthread.c and thread_win32.c for posix and windows systems respectively. In either case we see calls to GVL_UNLOCK_BEGIN here and here

EDIT

To be more precise:

Windows:

The windows implementation of native_sleep uses WaitForMultipleObjects which does indeed yield the remaining time slice, see: Does WaitForSingleObject give up a thread's time slice?

Posix:

The posix implementation uses pthread_cond_timedwait, which blocks the currently running thread.

Either way, the main thing to note here is that Ruby threads use the underlying thread blocking mechanisms of the OS and release the GVL with any call to sleep, allowing other threads to take control.

Community
  • 1
  • 1
photoionized
  • 5,092
  • 20
  • 23
  • 1
    Just to clarify, that being said, it's unlikely that the person writing that block of code was really trying to do what I described, so I kind of highly doubt whether or not those sleep calls would actually be useful. In fact, any time there is ruby application code with a call to sleep in it I'd be very likely to say that it's a code smell (though not all the time). – photoionized Apr 20 '16 at 20:56
  • Great answer. Are you familiar with the [Ruby Cross Reference](http://rxr.whitequark.org/mri/ident?i=rb_f_sleep)? It's a pretty great way to explore the MRI source. – Jordan Running Apr 20 '16 at 22:31
  • @Jordan: awesome resource, looks pretty similar to LXR, thanks for the info! – photoionized Apr 21 '16 at 03:22
  • Yep, it's generated by LXR! – Jordan Running Apr 21 '16 at 03:23
  • @Jordan: Ha, just saw the `This page was automatically generated by the 0.9.9 LXR engine.` :) – photoionized Apr 21 '16 at 03:26