From: Eric Hodel Date: 2012-02-28T09:36:27+09:00 Subject: [ruby-core:42985] Re: 50$ for answering my stackoverflow question about Ruby and GIL On Feb 27, 2012, at 12:10 PM, Grigory Petrov wrote: > I'm not so sure about that. Since TIME_QUANTUM_USEC is divided by 1000 for the call to WaitForSingleObject(), it's in microseconds, but this is only the maximum amount of time a thread may run for before being interrupted. > I assembled the following test code. It's very straightforward and > simple and will calculate an average splice time ( time scheduler will > assign to a thread that is not giving it up via Thread.pass): > > require 'thread' > require 'time' > time = 10 > items = [] > threads = [] > threads << Thread.new { loop { items << 1 } } > threads << Thread.new { loop { items << 2 } } > sleep time > threads.each( &:exit ).each( &:join ) > changes = 0 > for i in 1 ... items.count do > changes += 1 if items[ i ] != items[ i - 1 ] > end > printf( "Switch time is %.3f seconds\n", time.to_f / (changes + 1) ) This test code doesn't show switch time, it shows how fast two ruby threads can append items to a list. Each thread may switch multiple times during appending the item, or may not switch at all, but resume executing the same thread. The constants changed in USA's patch decrease the maximum possible runtime of a thread before the GVL is given to another thread. This helps prevent a CPU bound threads from starving another process (which you are doing). As USA also pointed out, running two CPU-heavy threads is not very good to the GVL, same as in Python. > The results are astonishing: > Ubuntu: 0.010 second, ok > OSX 10.7: 0.200 second, wtf? > Windows XP: 0.350 second!!! WTF. > > Switching threads 3-4 times per second on most popular OS'es is VERY > weird. Python slice is constant, around 10ms. And default thread > scheduling on all OS'es is around 10ms too. I ran this under Instruments on OS X, and got this report from the Scheduling instrument (counts thread context switches and intervals at the POSIX level): thread_start_func_1 150284 intervals in 10.72 seconds, average CPU usage of 38.89 �s thread_start_func_2 170662 intervals in 10.72 seconds, average CPU usage of 30.37 �s Running this yourself, you can look at the chart to see that sometimes ruby keeps running one thread for many milliseconds, but sometimes it rapidly switches between the two threads.