今日も元気にテクニカル

技術情報書きたいけど本ブログに書きたくないからこんな名前になりました。

REXMLが遅い。遅すぎる件について

最初は気のせいかと思ったが。

<?xml version="1.0" encoding="Shift-JIS" standalone="yes"?>
<items>
  <item>
    <url>http://newsing.jp/entry?url=headlines.yahoo.co.jp%2Fhl%3Fa%3D20070528-00000001-imp-sci</url>
    <title>東芝、「ぷよぷよ」もできる「gigabeat V」</title>
    <main_text></main_text>
    <picker>aplin</picker>
    <picktime>2007-05-29 01:04:32</picktime>
    <picker_eval>支持しない</picker_eval>
    <picker_com>gigabeatでぷよぷよをする意味など全くない。</picker_com>
    <pt>31</pt>
    <comments>
      <comment>
        <commenter>tera</commenter>
        <comtime>2007/05/29 02:45</comtime>
        <com_eval></com_eval>
        <com_text>Sの後継機出ないのかなぁ。</com_text>
        <nicecomment>0</nicecomment>
      </comment>
      <comment>
        <commenter>phantazy</commenter>
        <comtime>2007/05/29 10:32</comtime>
        <com_eval></com_eval>
        <com_text>ぷよぷよするな〜。</com_text>
        <nicecomment>0</nicecomment>
      </comment>
    </comments>
  </item>
  <item>
    (中略)
  </item>
</items>

上記のようなitem要素が200個あるXMLをREXMLによってパースしてみた。

require &#39;kconv&#39;
require &#39;rexml/document&#39;
include REXML

doc = REXML::Document.new File.open("newsing.xml","r")

1.upto(doc.root.elements.size) do |i|
  item = doc.root.elements["item[#{i}]"]
  puts item.text("url")
  puts item.text("title")
  puts item.text("main_text")
  puts item.text("picker")
  puts item.text("picktime")
  puts item.text("picker_eval")
  puts item.text("picker_com")
  puts item.text("pt")
  if item.text("comments")
    item.elements.each(".//comment") do |com|
      puts com.text("commenter")
      puts com.text("comtime")
      puts com.text("com_eval")
      puts com.text("com_text")
      puts com.text("nicecomment")
    end
  end
end

俺の想定では5秒くらいでレスポンス返ってくると思っていたが、CPU100%のまま固まってまう。検証用にこんなコードを書いてみた。

require &#39;kconv&#39;
require &#39;rexml/document&#39;
include REXML

require &#39;logger&#39;
log = Logger.new(STDOUT)
log.level = Logger::INFO
doc = REXML::Document.new File.open("V:/Prifiles/Prog/newsing/newsing.xml","r")
log.info(Time.now)
#=> I, [2007-06-01T22:20:32.640000 #4860]  INFO -- : Fri Jun 01 22:20:32 +0900 2007

1.upto(100) do |i|
  item = doc.root.elements["item[#{i}]"]
  item.text("url")
end

log.info(Time.now)
#=> I, [2007-06-01T22:20:44.728000 #4860]  INFO -- : Fri Jun 01 22:20:44 +0900 2007

1.upto(100) do |i|
  doc.root.elements["item[#{i}]"].text("url")
end

log.info(Time.now)
#=> I, [2007-06-01T22:20:56.434000 #4860]  INFO -- : Fri Jun 01 22:20:56 +0900 2007

100個要素を探してくるのに12秒?ありえない。これは俺の間違いじゃないと確信し「google:REXML 遅い」で検索したら出るわ出るわ。

こりゃREXMLを諦めてlibxmlでやるか、そもそもXMLを使うのを諦めた方がいいのかなぁ…。

http://www.dt8.jp/cgi-bin/sb/sb.cgi?eid=278
http://hiroumitani.blog.drecom.jp/archive/96

結構メインのところまで実装したのでがっかり。