Какая польза от потоков Ruby, если они на самом деле не параллельны?

Когда я впервые обнаружил потоки, я попытался проверить, действительно ли они работают так, как ожидалось, вызвав сон во многих потоках, а не вызывая сон в обычном режиме. Это сработало, и я был очень счастлив.

Но затем мой друг сказал мне, что эти нити на самом деле не параллельны, и что сон, должно быть, притворяется.

Итак, теперь я написал этот тест для реальной обработки:

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

И теперь мне очень грустно, потому что run_threads() не только не работал лучше, чем run_normal, он был еще медленнее!

Тогда зачем мне усложнять приложение потоками, если они на самом деле не параллельны?

** UPDATE **

@fl00r сказал, что я мог бы использовать преимущества потоков, если бы использовал их для задач ввода-вывода, поэтому я написал еще два варианта do_iterations:

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 => "some-name-#{i}"
  end
  TestModel.delete_all
end

Результаты производительности все те же: нормальный > нити.

Но теперь я не уверен, что моя виртуальная машина может использовать все ядра. Вернусь, когда проверю это.

6
задан HappyDeveloper 19 April 2012 в 11:24
поделиться