title: What use can I give to Ruby threads, if they are not really parallel?
body: <p>When I first discovered threads, I tried checking that they actually worked as expected by calling sleep in many threads, versus calling sleep normally. It worked, and I was very happy.</p>
  
  <p>But then a friend of mine told me that these threads weren't really parallel, and that sleep must be faking it.</p>
  
  <p>So now I wrote this test to do some real processing:</p>
  
  <pre><code>class Test
    ITERATIONS = 1000
  
    def run_threads
      start = Time.now
  
      t1 = Thread.new do
        do_iterations
      end
  
      t2 = Thread.new do
        do_iterations
      end
  
      t3 = Thread.new do
        do_iterations
      end
  
      t4 = Thread.new do
        do_iterations
      end
  
      t1.join
      t2.join
      t3.join
      t4.join
  
      puts Time.now - start
    end
  
    def run_normal
      start = Time.now
  
      do_iterations
      do_iterations
      do_iterations
      do_iterations
  
      puts Time.now - start
    end
  
    def do_iterations
      1.upto ITERATIONS do |i|
        999.downto(1).inject(:*) # 999!
      end
    end
  end
  </code></pre>
  
  <p>And now I'm very sad, because run_threads() not only didn't perform better than run_normal, it was even slower!</p>
  
  <p>Then why should I complicate my application with threads, if they aren't really parallel?</p>
  
  <p><strong>** UPDATE **</strong></p>
  
  <p>@fl00r said that I could take advantage of threads if I used them for IO tasks, so I wrote two more variations of do_iterations:</p>
  
  <pre><code>def do_iterations
    # filesystem IO
    1.upto ITERATIONS do |i|
      5.times do
        # create file
        content = "some content #{i}"
        file_name = "#{Rails.root}/tmp/do-iterations-#{UUIDTools::UUID.timestamp_create.hexdigest}"
        file = ::File.new file_name, 'w'
        file.write content
        file.close
  
        # read and delete file
        file = ::File.new file_name, 'r'
        content = file.read
        file.close
        ::File.delete file_name
      end
    end
  end
  
  def do_iterations
    # MongoDB IO (through MongoID)
    1.upto ITERATIONS do |i|
      TestModel.create! :name =&gt; "some-name-#{i}"
    end
    TestModel.delete_all
  end
  </code></pre>
  
  <p>The performance results are still the same: normal > threads.</p>
  
  <p>But now I'm not sure if my VM is able to use all the cores. Will be back when I have tested that.</p>