From: Robert Klemme Date: 2011-09-06T18:01:59+09:00 Subject: Re: why the sleep statement produces this result for our embedded ruby? On Tue, Sep 6, 2011 at 10:11 AM, Balasaheb S. wrote: > We are testing thread coperation for our embedded ruby. We have a C ruby > extension implementented the following methods > 1. longRunningMethod() > 2. shortRunningMethod(). > > > Here is a code for the checking the thread cooperation > > > //file > test.rb > > > require 'mymodule' > > $a = 0; > obj = MyModule::MyClass.new > t1 = Thread.new{$a = obj.veryLongRunningOperation(); puts "doneLong"} > sleep 1 > $a = obj.shortOperation() > puts "doneShort" > t1.join > > > We have ensured that the longRunningMethod takes more than 1sec(5sec) > for execution using nested for loops > As per our understanding, the shortRunningMethod should be completed > first and then longRunningMethod. > > However we observed this only when we did not have any sleep command. > But when we introduced the "sleep 1" statement. The longRunningMethod > gets executed first and then shortRunningMethod > > Anyone would give us the pointers as to why the sleep statement produces > this result? > > [We are using ruby 1.8.6] Thanks in advance. 1.8.6 has green threads and does not use native threads. This means there is no real parallel execution. It may be that the sleep triggers Ruby's scheduler to pick another thread which happens to be stuck in the long C function call. If you think about it it's a reasonable approach because usually any other thread than the sleepy thread will have to do work to do. Behavior may be different on 1.9.* since that uses native threads. However, I would not yet rely on real thread concurrency. For that you need JRuby. See this test on my machine (4 cores): 10:51:05 ~$ allruby par.rb CYGWIN_NT-5.1 padrklemme2 1.7.9(0.237/5/3) 2011-03-29 10:10 i686 Cygwin ======================================== ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin] par 1 2.484000 0.000000 2.484000 ( 2.499000) par 2 5.047000 0.000000 5.047000 ( 5.042000) par 3 7.516000 0.000000 7.516000 ( 7.511000) par 4 9.906000 0.000000 9.906000 ( 9.905000) ======================================== ruby 1.9.2p290 (2011-07-09 revision 32553) [i386-cygwin] par 1 1.328000 0.000000 1.328000 ( 1.323000) par 2 2.625000 0.000000 2.625000 ( 2.633000) par 3 4.094000 0.000000 4.094000 ( 4.080000) par 4 5.344000 0.000000 5.344000 ( 5.346000) ======================================== jruby 1.6.3 (ruby-1.8.7-p330) (2011-07-07 965162f) (Java HotSpot(TM) Client VM 1.6.0_27) [Windows XP-x86-java] par 1 1.219000 0.000000 1.219000 ( 1.172000) par 2 1.218000 0.000000 1.218000 ( 1.218000) par 3 1.110000 0.000000 1.110000 ( 1.110000) par 4 1.562000 0.000000 1.562000 ( 1.562000) ======================================== jruby 1.6.3 (ruby-1.9.2-p136) (2011-07-07 965162f) (Java HotSpot(TM) Client VM 1.6.0_27) [Windows XP-x86-java] par 1 1.390000 0.000000 1.390000 ( 1.390000) par 2 1.844000 0.000000 1.844000 ( 1.844000) par 3 3.422000 0.000000 3.422000 ( 3.422000) par 4 3.719000 0.000000 3.719000 ( 3.719000) ======================================== 10:52:13 ~$ cat -n par.rb 1 2 require 'benchmark' 3 4 for par in 1 .. 4 5 printf "par %2d\n", par 6 7 puts(Benchmark.measure do 8 th = (1..par).map do 9 Thread.new { 10_000_000.times { 1 + 2 }} 10 end 11 12 th.each {|t| t.join} 13 end) 14 end 15 16 10:52:21 ~$ Note that in spite of native threads and absence of IO ruby 1.9.2 does not scale better than ruby 1.8.7. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/