2007-10-01
■[Ruby] Rubyでスレッド
Rubyで http ごしにデータを取得するには、'open-uri' を使えば簡単に出来るけど、複数の URL から取得するとき、単純に
require 'open-uri' e1 = open("http://www.hogehoge.com/").read e2 = open("http://www.fugafuga.net/").read
と直列にしてしまうと最初のリクエストが完了するまでブロックされてしまい、読み終わってからようやく次のリクエストを出すことになってしまう。アイドル時間がもったいないのでなんとかしたい。そこでスレッドを使ったら無駄な待ち時間が減るんじゃなかろうかと思った。
なにかお題を…てことで、livedoorクリップとはてなブックマークの両方から結果を取得するなんてどうだろう、と思って両APIを見てみた。
RESTしか使ったことねーから XML-RPC なんてわからねーよ!と思ったけど、Ruby での XML-RPC の使い方を動かしてみたらそのまま動いた。
Rubyでスレッドのやりかたは逆引きRuby - スレッドを見たらバッチリ、で完成。
require "xmlrpc/client" def get_xmlrpc( host, path, method, *args ) # Make an object to represent the XML-RPC server. server = XMLRPC::Client.new( host, path ) # Call the remote server and get our result server.call( method, *args ) # <= *args で配列を展開して引数に渡す end def get_livedoor_clip_count( urls ) get_xmlrpc( "rpc.clip.livedoor.com", "/count", "clip.getCount", *urls ) end def get_hatena_bookmark_count( urls ) get_xmlrpc( "b.hatena.ne.jp", "/xmlrpc", "bookmark.getCount", *urls ) end # 普通に取得 def get_by_normal( urls ) lc = get_livedoor_clip_count( urls ) hb = get_hatena_bookmark_count( urls ) return lc, hb end # スレッドを使って取得 def get_by_thread( urls ) lc = hb = nil # LivedoorClip の件数取得スレッド tlc = Thread.new do lc = get_livedoor_clip_count( urls ) end # HatenaBookmark の件数取得スレッド thb = Thread.new do hb = get_hatena_bookmark_count( urls ) end # 全スレッドの終了待ち [tlc, thb].map {|t| t.join } return lc, hb end # ベンチマーク require 'benchmark' Urls = %w{ http://clip.livedoor.com/ http://b.hatena.ne.jp/ http://del.icio.us/ } lc = hb = nil if ARGV[0] == "n" Benchmark.bm(8) do |x| x.report('normal:') { lc, hb = get_by_normal( Urls ) } end else Benchmark.bm(8) do |x| x.report('thread:') { lc, hb = get_by_thread( Urls ) } end end Urls.each do |key| puts "\t#{key}\tlc=#{lc[key]}, hb=#{hb[key]}" end
一度に両方やってしまうと、キャッシュされてしまうのか後に実行したほうが速くなってしまっていたので、コマンドラインの引数で処理を分けるようにした。
実行結果:
$ ruby test.rb n # <= 通常版 user system total real normal: 0.090000 0.070000 0.160000 ( 0.350000) http://clip.livedoor.com/ lc=214, hb=365 http://b.hatena.ne.jp/ lc=123, hb=1179 http://del.icio.us/ lc=68, hb=838 $ ruby test.rb # <= スレッド版 user system total real thread: 0.060000 0.110000 0.170000 ( 0.210000) http://clip.livedoor.com/ lc=214, hb=365 http://b.hatena.ne.jp/ lc=123, hb=1179 http://del.icio.us/ lc=68, hb=838
一応スレッドを使ったほうが実時間では速くなってるっぽい?スレッド切り替えとか入る分、システム時間は少し余分にかかってるっぽい。ユーザ時間まで減るのはわかりませんが…。
しかし、スレッドを使った場合でも使ってない場合と比べてそんなに複雑さは変わらないほど楽チンなので、これならやってみようっていう気になりますね。
トラックバック - http://d.hatena.ne.jp/mokehehe/20071001/thread
リンク元
- 5 http://reader.livedoor.com/reader/
- 2 http://d.hatena.ne.jp/keyword/nil
- 2 http://d.hatena.ne.jp/keyworddiary/Ruby
- 1 http://72.14.235.104/search?q=cache:Nz13U7OSFycJ:d.hatena.ne.jp/johzan/20071003+[Ruby]+Rubyでスレッド+サルでもわかる&hl=ja&ct=clnk&cd=2&client=opera
- 1 http://b.hatena.ne.jp/entry/http://b.hatena.ne.jp/
- 1 http://blog-search.yahoo.co.jp/search?p=ruby+thread&ei=UTF-8
- 1 http://d.hatena.ne.jp/Ashizawa/20071002/1191293401
- 1 http://d.hatena.ne.jp/chaichanPaPa/edit?date=20071006
- 1 http://d.hatena.ne.jp/johzan/
- 1 http://d.hatena.ne.jp/keyword/TLC