Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Thread の利用事例紹介

390 views

Published on

Ruby Thread

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Thread の利用事例紹介

  1. 1. Thread の利用事例紹介 2018/06/28 Meguro.rb #16
  2. 2. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 1自己紹介 Tomoya Kawanishi a.k.a. @cuzic エネチェンジ株式会社 チーフエンジニア 電力会社、ガス会社を切り替えるなら、エネチェンジ経由で! 一般家庭も!法人も! Ruby関西の中の人 7月21日に 大阪Ruby会議01 を開催予定 大手町.rb の中の人 次回、7月10日(火)Otemachi.rb #8 の開催を予定 東京駅、各線大手町駅から直結! テーマは「Dir、File、IO」 Ruby の初級者がメインターゲット
  3. 3. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 おさらい meguro.rb #8 での発表 tsort について AWS の費用を事業ごとの分配をするために、 AWS リソースをタグ付け 内部的には、aws コマンドを繰り返し実行 実行結果を元にグラフ構造を構築 トポロジカルソートを行う tsort ライブラリを利用 グラフ構造を元に、EC2 のタグをほかのリソースに展開 2 EC2 EBS スナップ ショット AMI ENI EIP
  4. 4. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 もっと速くしたい 実行してみたところ、わりと時間がかかった 5分くらい もっと速くしたい! aws コマンドの実行に時間を要しているのは明らか aws コマンドを並列実行するともっと速くできる! 3
  5. 5. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 処理内容 遅いのは、AWS リソースの情報取得のところと、 タグ付のところ 特に、タグ付のところが遅かった 4 グラフ構造の構築 トポロジカルソート AWS リソースのタグ付 AWS リソースの情報取得 (AWS コマンドの発行) AWS コマンドを 4回発行 describe-instances describe-network-interfaces describe-images describe-snapshots AWS コマンドを リソースの数、 タグの数に応じて、繰り返し実行
  6. 6. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 情報取得(メインスレッド側) Threadを使った内部実装は意識させない設計 引数: aws コマンドの引数 ブロック引数: aws コマンドの実行結果(標準出力)の各行 Thread#join を各スレッドで実行。情報取得終了を待つ 5 def each_ebs_snapshot query = "Snapshots[].[VolumeId, SnapshotId]" aws_lookup(%(ec2 describe-snapshots --query "#{query}")) do |line| volume_id, snapshot_id = line.chomp.split("¥t") yield volume_id, snapshot_id end end ワーカスレッドで 実行される def join_lookup_threads @lookup_threads.each &:join end 呼び出すとき 各スレッドの終了を待つとき @lookup_threads は ワーカスレッドの配列
  7. 7. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 AWSリソースの情報取得(ワーカスレッド側) スレッド内では Thread.new の引数だけを使用 そのスレッド内でのローカルコピーが作られる 他のスレッドでの更新が原因での不具合とかが起きない aws コマンドを実行し、出力結果を1行ごとに ブロック引数として呼び出し元に渡す 1つのコマンドを1つのスレッドで実行 あとで待ち合わせするため Thread を配列に保持 6 def aws_lookup(command) @lookup_threads << Thread.new(command) do |cmd| cmdline = "aws #{cmd} --output text" IO.popen(cmdline, "r+") do |io| io.each_line do |line| yield line end end end end Thread 中で使う command を引数と している
  8. 8. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 タグ付(メインスレッド側) タグ付けでは、異なるリソースを対象に繰り返し AWS コマンドを発行する ワーカスレッドで、AWSコマンドを並行実行する スレッド間通信には Queue を使用する Ruby 2.3以降は組み込みライブラリ Queue#enq を利用 出力結果は使用しない AWSコマンドの成功/失敗も気にしない(Fire and Forget) 複数リソースに対するタグ付けを1回で処理 shellwords ライブラリの Array#shelljoin メソッドを使用 7 def create_tags(resources, tags) return if tags.empty? args = ["--resources", resources.shelljoin, "--tags", tags.shelljoin] @aws_queue.enq %(ec2 create-tags #{args.shelljoin}) end
  9. 9. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 AWS リソースのタグ付(ワーカスレッド側) Queue#deq で、キューからオブジェクトを取り出せる while command = queue.deq は Thread 処理でよく使うイデ ィオム nil 以外の場合、ループの中の処理を行う nil を受け取るとループから抜ける 8 def start_aws_thread Thread.start do |t| while command = @aws_queue.deq cmdline = "aws #{command}" system cmdline end end end end nil 以外の場合はループの中を実行 nil のときは、ループを抜ける
  10. 10. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 タグ付(メインスレッド側) 開始と終了 ワーカスレッドを開始すると、配列に保持する ワーカスレッドを終了するため、nil を Queue に渡す それぞれの Thread が終了するのを join で待つ 9 # ワーカスレッドの開始 def start_tagging_threads @thread_num.times do @tagging_threads << start_aws_thread end end # ワーカスレッドの終了 def join_tagging_threads @thread_num.times do @aws_queue.enq nil end @tagging_threads.each &:join end スタートしたスレッドを配列に保持 ワーカスレッドの数だけ nil をキューに送信 ワーカスレッドの終了を join で待つ
  11. 11. Meguro.rb #16 発表資料 「Thread の利用事例紹介」 まとめ AWS のリソースへのタグ付を例に 簡単な Thread の使い方を説明しました キャラの違う2つの利用例で説明しました リソース情報取得では、 1個のコマンドを1個の Thread で実行 外部コマンドの出力結果を利用する Thread の start 時の引数だけを Thread 内で利用する タグ付処理では 複数のコマンドを、複数の Thread で実行 外部コマンドの出力結果は利用しない。(単に捨てる) Queue でコマンドの受け渡しをする みなさまの開発のときにお役に立てると嬉しいです 10
  12. 12. 11 ご清聴ありがとう ございました

×