async gem
https://github.com/socketry/async
Fiberベースで並行処理をサポートするgem
事例
並行・並列、そしてAsync
マルチスレッドやマルチプロセスと違い、並列性がない
CPUの処理を多重化できない
一見デメリットだがこの特性を活かし、I/Oバウンドな処理においてスループットを上げるのに有用
Fiberを直接使うよりもAsyncを使うと便利
code:ruby
require 'bundler/inline'
require 'csv'
gemfile do
source 'https://rubygems.org'
gem 'async'
end
enum = CSV.foreach('input.csv').lazy.map{|row| row'path' }.each_slice(1000)
Async do
10000.times do
Async do
loop do
paths = enum.next
# do something
end
end
end
end
上記をThreadで書き直すと以下のようになるが動作しない
code:ruby
require 'bundler/inline'
require 'csv'
gemfile do
source 'https://rubygems.org'
gem 'async'
end
enum = CSV.foreach('input.csv').lazy.map{|row| row'path' }.each_slice(1000)
threads = []
10000.times do
threads << Thread.new do
paths = enum.next
# do something
end
end
threads.each(&:join)
ただし以下のエラーが起きる
code:txt
#<Thread:0x000000011d872878 s.rb:16 run> terminated with exception (report_on_exception is true):
s.rb:17:in `next': attempt to resume a resumed fiber (double resume) (FiberError)
複数スレッドから同じEnumeratorにアクセスし、Enumeratorが内部的に利用しているFiberを二重にresumeしているため
同一のFiberを別のスレッドでresumeしないように書くのは難しいため、