Существует ли ограничение на количество потоков, которые Ruby может запускать сразу?

Если нет, то какой максимум пока остается эффективным?

Я создаю 14 потоков, каждый из которых открывает список URL-адресов (около 500), создает новый поток для каждого, который затем загружает его, и добавляет его в MySQL db. Размер пула MySQL установлен равным 50.

Это задача rake в RoR.

Будет ли это работать лучше, используя Kernal#fork или какой-либо другой метод?

Ответ 1

Что ж, поскольку ваши потоки будут связаны с вводом-выводом, хорошая новость заключается в том, что оба потока Ruby 1.8 и 1.9 будут работать для этого. В Ruby 1.8 используются "потоки пользовательского пространства", то есть при создании новых потоков в Ruby новые потоки ОС не создаются. Это плохо для многозадачности ЦП, так как на самом деле одновременно работает только один поток Ruby, но хорошо для многозадачности ввода-вывода. Ruby 1.9 использует реальные потоки, и подойдет для любого из них.

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

Я бы начал с малого: 10 или 20 потоков работают одновременно. Увеличьте или уменьшите это в зависимости от нагрузки на сервер, пропускной способности и т.д. Также существует проблема одновременных подключений к базе данных MySQL. В зависимости от того, как настроены ваши таблицы и насколько они велики, попытка одновременно вставить слишком много данных не будет работать очень хорошо.

Ответ 2

require 'open-uri'
a = 'http://www.example.com ' * 30
arr = a.split(' ')

arr.each_slice(3) do |group|
  group.map do |site|
    Thread.new do
      open(site)
      p 'finished'
    end
  end.each(&:join)
end

Ответ 3

С Ruby 1.8 он практически ограничен количеством памяти. Вы можете создавать десятки тысяч потоков для каждого процесса. Интерпретатор Ruby обрабатывает управление потоками и создается только один или два собственных потока. Это не так многозадачность, когда CPU переключается между потоками.

Ruby 1.9 использует собственные потоки. Предел, по-видимому, является тем, что разрешено ОС. Просто для тестирования я могу создать более 2000 потоков на моем Mac с Ruby 1.9 до того, как ОС будет запрещена.

Обратите внимание, что с тысячами потоков для процесса это не очень хорошая идея. Планирование потоков становится бредом задолго до этого.