Skip to content
Advertisement

sleep 0 has special meaning?

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.

Advertisement

Answer

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.

Advertisement