LoginSignup
11
4

More than 3 years have passed since last update.

Rubyの並列処理

Last updated at Posted at 2019-06-12

はじめに

最近、複数メソッドを並列で処理するコーティングを行い、concurrent-rubyについて学んだので簡単にまとめました。

concurrent-rubyとは

concurrent-rubyは、並行処理のデザインパターンを元に作られたライブラリ。

サンプル

concurrent-rubyは、様々な作法が存在しますが、ネットで検索すると、単数形のPromiseやFutureなどと色々な書き方が出てきます。最近、Promisesで統一されつつあるらしいので、Concurrent::Promisesのサンプルを紹介します。

まずは、並列に実行したいProcオブジェクトを作成するメソッド(p1、p2、p3)を準備。今回は、それぞれのメソッドの中に、1secずつずらしたsleepを設けます。

def p1
  lambda {
    start_time = Time.now
    sleep 1
    return "p1 => start time: #{start_time}, finish_time: #{Time.now}s"
  }
end

def p2
  lambda {
    start_time = Time.now
    sleep 2
    return "p2 => start time: #{start_time}, finish_time: #{Time.now}s"
  }
end

def p3
  lambda {
    start_time = Time.now
    sleep 3
    return "p3 => start time: #{start_time}, finish_time: #{Time.now}s"
  }
end

pry(main)> p1
=> #<Proc:0x000055bb4bf3ad48@(pry):68 (lambda)>
pry(main)> p2
=> #<Proc:0x000055bb4bf16df8@(pry):75 (lambda)>
pry(main)> p3
=> #<Proc:0x000055bb4bef7660@(pry):91 (lambda)>

それぞれの処理を実行するスレッドを作成します。以下の状態では、pendingとなっており、まだ処理は実行されていません。

tasks = [p1, p2, p3].map { |p| Concurrent::Promises.future { p.call } }

=> [#<Concurrent::Promises::Future:0x000055bb4be2aac0 pending>,
 #<Concurrent::Promises::Future:0x000055bb4be29b20 pending>,
 #<Concurrent::Promises::Future:0x000055bb4be289f0 pending>]

zipとういうメソッドが用意されているのでそれを使用すると、同時にスレッドが実行され、それらの返り値が配列にまとめられます。

pry(main)> Concurrent::Promises.zip(*tasks).value! 
=> ["p1 => start time: 2019-06-12 18:23:01 +0900, finish_time: 2019-06-12 18:23:02 +0900s",
 "p2 => start time: 2019-06-12 18:23:01 +0900, finish_time: 2019-06-12 18:23:03 +0900s",
 "p3 => start time: 2019-06-12 18:23:01 +0900, finish_time: 2019-06-12 18:23:04 +0900s"]

start timeは実行時刻。同じ時刻(2019-06-12 18:23:01 +0900)から同時に実行されたことがわかります。また、finish_timeは1秒ずつずれています。逐次処理の場合は、sleepタイム毎に時刻がずれるため、これが並列処理で実行されていることがわかります。

まとめ

簡単にですが、Rubyの並列処理についてまとめました。今回は、非常に簡単な例ですが、まともに使おうとするとかなり手こずると思います。Railsアプリケーションに組み込もうとして実装を試みましたが、実装が複雑化してデバックがしにくくなるため、導入を断念しました。正直、Ruby自体が並列処理に向いてなさそうです。Railsアプリケーションならば、Sidekiqなどを使用して無理せず実装した方が良さそうですね。

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4