Использование Thread.new в действии Rails - PullRequest
1 голос
/ 10 мая 2019

При использовании многопроцессорного сервера приложений и запуске Thread.new (порождая несколько потоков) в действии контроллера достигается параллелизм?Или GIL предотвращает это?

Ответы [ 2 ]

3 голосов
/ 10 мая 2019

Глобальная блокировка интерпретатора (GIL) предотвращает запуск более одного потока Ruby в любой момент времени, что приводит к ограничению Ruby только одним ядром.Кроме того, они являются реальными потоками.

Если вам нужен истинный параллелизм, вам нужно запустить Ruby без GIL, как JRuby.

При этом потоки в Ruby подходят для многихоперации, в которых вы не закрепляете ядро ​​процессора.Если вы, вероятно, вам следует создать фоновые задания для этих операций через ActiveJob .При необходимости они могут выполняться в одном или нескольких процессах в разных системах.

2 голосов
/ 10 мая 2019

Ответ @tadman совершенно правильный, я просто хочу немного расширить 3 абзаца.

Когда темы лучше использовать в MRI Ruby? Главным образом, если вы связаны операциями ввода-вывода. Итак, если у вас есть действие Rails, когда у вас много запросов к базе данных и / или http-запросов, вы можете сделать их в потоке, сохранить запрос в локальной переменной потока, объединить их вместе и затем обработать локальные переменные потока. Таким образом вы достигнете заметного улучшения производительности.

Это может выглядеть так:

threads << Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
  t = Thread.current
  t[:variable_name] = Model.find_by(col: data)
  end
end
joined_threads = threads.map &:join
joined_threads.each do |t|
  t.keys.each do |key|
    k = key.to_s.downcase
    next if k.start_with?("active") || k.start_with?("__")
    instance_variable_set "@#{key}", t[key]
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...