From: Prashant Srinivasan Date: 2008-10-08T09:09:34+09:00 Subject: Re: Concurent (using threads) slower than sequential -doubt Carlos, that sounds about correct. I did some similar tests early this year[1]. Basically your problem is that Ruby runs on one kernel thread/LWP irrespective of how many user land threads you create. It's expensive to switch between threads(cost varies depending on which hardware platform you're running on) - so these two factors combine to make it slower for you when you use threads. JRuby was almost just as bad until JRuby 1.1.1 after which it started doing better with threads(this was due to a bug fix by Charles [2]). It's now much better at scaling with threads compared with MRI, but still quite poor in absolute terms[3] - it's scalability on an embarrassingly threaded program eroded 54% jumping from 1 to 2 threads and became worse after that. (*Caveat:* My numbers are old, they're from March, and things may have gotten much better since!) [1] http://blogs.sun.com/prashant/resource/files/jruby-ruby-comparison.xls [2] Ref to Charles' entry http://blog.headius.com/2008/04/shared-data-considered-harmful.html [3] http://blogs.sun.com/prashant/resource/files/jruby-threads.xls -ps Carlos Ortega wrote: > Hi Folks. > While starting to study the benefits of using threads in Ruby, I tried > to solve the following problem: > > I have 3 text files ( numbers0.txt, numbers1.txt, c:\numbers2.txt ), > each file contains a very large list of numbers. > I attempt to read and compute each file by using a different thread. > Finally I tried to sum all subtotals to provide the final result. > > Here is the code. > =================== > > require 'thread' > m_threads = [] > > print "INITIAL TIME := ", initial_time = Time.now, "\n" > 3.times do |i| > m_threads[i] = Thread.new do > total_per_thread = 0 > case i > when 0 then path = "C:\\numbers0.txt" > when 1 then path = "C:\\numbers1.txt" > when 2 then path = "C:\\numbers2.txt" > end > File.open( path, "r" ) do |m_file| > while line = m_file.gets > total_per_thread = line.to_i + total_per_thread > end > Thread.current[:INDEX] = total_per_thread > end > end > end > > result = 0 > m_threads.each{ |t| t.join; result = t[:INDEX] + result; } > > print "FINAL TIME := ", final_time = Time.now, "\n" > print "TOTAL TIME := ", total_time = final_time-initial_time, "\n" > print "Total := ", result, "\n" > > ======================================= > Output (CONCURRENT - Using Threads): > > INITIAL TIME := Sun Oct 05 22:07:26 -0500 2008 > > FINAL TIME := Sun Oct 05 22:07:38 -0500 2008 > TOTAL TIME := 11.485 > Total := 1150000000 > ======================================== > > I verified and each thread made the job, result is OK too. > I also solved the same problem by using a sequential program with no > threads at all > Here is the code: > > print "INITIAL Time := ", initial_time = Time.now, "\n" > > paths = [ "C:\\numbers0.txt", "C:\\numbers1.txt", "C:\\numbers2.txt" ] > result = 0 > for m_path in paths > File.open( m_path, "r+" ) do |m_file| > while line = m_file.gets > result = line.to_i + result > end > end > end > > print "FINAL time := ", final_time = Time.now, "\n" > print "TOTAL time := ", total_time = final_time - initial_time, "\n" > print "Total := ", result, "\n" > > ======================================= > Output: (SECUENCIAL- NO Threads) > > INITIAL TIME := Sun Oct 05 22:34:47 -0500 2008 > FINAL TIME := Sun Oct 05 22:34:57 -0500 2008 > TOTAL TIME := 10.656 > Total := 1150000000 > > ======================================= > As you see, the thread based program run slower. > I thought that by using threads it will be faster, but it didn't....Why > is it slower? > > Any help will be very appreciated > -- Prashant Srinivasan F/OSS Enthusiast Sun Microsystems, Inc. http://blogs.sun.com/prashant GnuPG key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x82FBDE5A