すがブロ

sugamasaoのhatenablogだよ

となりの ATND さんが遅いんだよね

ガチで遅い

一回のレスポンス返すまでで10秒くらい掛かってる。
よくよく調べてみると、Atnd4r の get_event_list と get_user_list が遅いんだね。
つまり公開メソッド両方じゃんw ってわけなんだけど、両方とも中ではほとんど同じメソッドを使っているので、どこかにボトルネックがあるのは間違いない。

というわけで、調べてみる

Benchmark を取ってみた。
irb(main):117:0> # イベントサーチ用(http://atnd.org/events/1701)
irb(main):118:0* Benchmark.bm(30) do |x|
irb(main):119:1* x.report("get_xml") { @xml = Atnd4r.get_xml("/events/", Atnd4r.make_query({:event_id=>1701, :count=>200}))}
irb(main):120:1> x.report("parse_common") { envent = Atnd4r.parse_common_xml(@xml)}
irb(main):121:1> x.report("parse_events") { envent = Atnd4r.parse_events_xml(@xml)}
irb(main):122:1> end
                                    user     system      total        real
get_xml                         0.000000   0.000000   0.000000 (  0.682978)
parse_common                    0.010000   0.000000   0.010000 (  0.001616)
parse_events                    0.040000   0.000000   0.040000 (  0.041034)
=> true
irb(main):123:0> 
irb(main):124:0* # 出欠確認用API(http://atnd.org/users/1500)
irb(main):125:0* Benchmark.bm(30) do |x|
irb(main):126:1* x.report("get_xml") { @xml = Atnd4r.get_xml("/events/users/", Atnd4r.make_query({:user_id=>1500, :count=>200}))}
irb(main):127:1> x.report("parse_common") { envent = Atnd4r.parse_common_xml(@xml)}
irb(main):128:1> x.report("parse_users") { envent = Atnd4r.parse_users_xml(@xml)}
irb(main):129:1> end
                                    user     system      total        real
get_xml                         0.420000   0.050000   0.470000 (  3.215565)
parse_common                    0.010000   0.000000   0.010000 (  0.001608)
parse_users                     1.910000   0.010000   1.920000 (  1.928213)
=> true
結果を分析してみよう

get_xml は HTTP で atnd api を叩いている所なので、これ以上縮めるのは難しいような気がする。
parse_common は ATND APIXML でイベント用と出欠確認用で共通の部分を Ruby オブジェクトにしているので、結果からも分かる通り、大した処理では無いのだろう。
というわけで、短くできる余地は parse_events_xml/parse_users_xml メソッドなんでしょうね。
parse_evnets_xml の方が処理時間が短いけれど、実質同じようなメソッドだし。単純にイベントデータのデータ量が少ない分、処理時間も短いと考えられる。

さらにソースを読んで行くと(自分のだけどw)

最終的には AtndEvent クラスの生成で XML のパースもしてるので、そっちで時間を食っているように思える。
で、試しに XML から Ruby の文字列や数値オブジェクトへ変換している部分で時間使ってるかなーと考えて、処理をコメントアウトにして試してみた。

その結果
irb(main):017:0> # イベントサーチ用(http://atnd.org/events/1701)
irb(main):018:0* Benchmark.bm(30) do |x|
irb(main):019:1* x.report("get_xml") { @xml = Atnd4r.get_xml("/events/", Atnd4r.make_query({:event_id=>1701, :count=>200}))}
irb(main):020:1> x.report("parse_common") { envent = Atnd4r.parse_common_xml(@xml)}
irb(main):021:1> x.report("parse_events") { envent = Atnd4r.parse_events_xml(@xml)}
irb(main):022:1> end
                                    user     system      total        real
get_xml                         0.010000   0.010000   0.020000 (  2.084429)
parse_common                    0.000000   0.000000   0.000000 (  0.001553)
parse_events                    0.040000   0.000000   0.040000 (  0.041062)
=> true
irb(main):023:0>
irb(main):024:0* # 出欠確認用API(http://atnd.org/users/1500)
irb(main):025:0* Benchmark.bm(30) do |x|
irb(main):026:1* x.report("get_xml") { @xml = Atnd4r.get_xml("/events/users/", Atnd4r.make_query({:user_id=>1500, :count=>200}))}
irb(main):027:1> x.report("parse_common") { envent = Atnd4r.parse_common_xml(@xml)}
irb(main):028:1> x.report("parse_users") { envent = Atnd4r.parse_users_xml(@xml)}
irb(main):029:1> end
                                    user     system      total        real
get_xml                         0.390000   0.060000   0.450000 (  3.387357)
parse_common                    0.000000   0.000000   0.000000 (  0.001519)
parse_users                     1.820000   0.010000   1.830000 (  1.844556)
=> true
うは

かわらねーwww
こうなると、他に思い当たる節は XML のアクセスくらいしかなさそう。
xml.elements['hoge']のようなアクセスが遅いのかな。いやでも、特に深い子要素にアクセスするようなことはしてないんだよなぁ。
アクセス方法云々じゃなくて、 REXML での要素へのアクセスが自体が遅いのか。。。
いやー困りましたね/(^o^)\
この件はちょっと寝かして、また後で考えてみようw