目次


性能かコーディング量か?RubyにおけるXMLライブラリーの選び方

REXMLとLibXML-Rubyのパフォーマンスを比較する

Comments

Rubyを使ってXMLデータを扱おうとした時、私たちは幾つかの選択肢からその方法を選ぶことができます。それぞれのライブラリーには特徴がありますが、実用面から考えた時にはパフォーマンス面での性能が利用可否に大きく影響します。本稿では主要なライブラリーとして特にREXMLとLibXml-Rubyの2つに注目して、それらのパフォーマンスについて考察します。
一般的には、DOMを使うよりもストリーミング処理を行った方がパフォーマンスに優れると言われています。また、REXMLよりもLibXml-Rubyの方がパフォーマンスに優れるといわれ、簡単なベンチマークの結果がLibXml-Rubyのホームページにも紹介されています。
本稿では実際にXMLデータに対して処理を行い、パフォーマンス面でこの2つのライブラリーにどの程度の違いがあるかについて確認し、それぞれを利用する上でのスイートスポットを探したいと思います。処理を行うXMLデータには、現実的なデータとしてXBRLを利用します。

Ruby向けXMLライブラリー

RubyでXMLを扱う方法の一つはRubyの標準添付ライブラリーに含まれるREXMLを使う方法です。REXMLはRuby 1.8からのフィーチャーで、添付ライブラリー故にインストールなどを気にしなくていいというメリットが有ります。また、REXMLはpure Rubyで作られているという特徴があります。REXMLには、XMLデータを扱うために次のようなAPIが用意されています。

  • ツリー・ベースのAPI(DOM)
  • SAXライクなストリームAPI
  • SAX2ベースのAPI
  • プル・パーサーAPI

また、REXML以外に外部ライブラリーを利用することができます。そのようなライブラリーの一つにLibXml-Rubyがあります。LibXml-RubyはCで作られているGNOME LibXml2 XMLツールキットのRubyバインディングです。LibXml-Rubyには、XMLデータを扱うために次のようなAPIが用意されています。

  • ツリー・ベースのAPI(DOM)
  • Reader(プル・パーサー)API
  • SAX API

REXMLのインストール

REXMLはRuby 1.8以降で標準添付ライブラリーとして配布されています。RubyをインストールするだけでOKです。

LibXml-Rubyのインストール

LibXml-RubyはRubyGemsを利用してインストールすることができます。必要に応じてRubyGemsのupdateを行います。特にRuby One-Click Installerを利用している場合には、この作業が必要です。

リスト1. RubyGmesのアップデート
gem update –-system

それからLibXml-Rubyのインストールを行います。

リスト2. LibXml-Rubyのインストール
gem install libxml-ruby

パフォーマンス測定を行った処理

今回、REXMLとLibXml-Rubyでパフォーマンスを比較するに当たり、現実的なXMLデータとしてXBRLデータを用い、次のような処理を含むプログラムについて処理時間を測定しました。

  • 処理1:XBRLインスタンスのXMLデータを読み取り、{ノード名->値}のハッシュに読み取る
  • 処理2:XBRLインスタンスに対応するXMLスキーマと、各ノードのラベル名を定義するXMLファイルを読み取り、XBRLインスタンスの各ノード名とラベル名のマッチングを行い、{ノード名->ラベル名}のハッシュに読み取る

処理1は1つのXML文書のみを扱い、比較的簡単な処理のみを行うという特徴があります。
処理2は複数のXML文書を扱い、XML文書の中の複数のデータのマッチングを行うなど、処理1に比べ、より多くのXML文書を扱い、処理内容も複雑という特徴があります。
対象とするデータは東京証券取引所により提供されている決算短信のサンプル・データ、および、U.S. GAAPの2008年度のタクソノミーのサンプルとして提供されているデータを利用しました。

また、REXMLとLibXml-Rubyのそれぞれのライブラリーについて、XML文書をツリーとして扱うDOMと、ストリーム処理を行う方法とで処理時間を比較しました。ストリーム処理には大きく分けてプッシュ型とプル型の2種類があります。プッシュ型はパーサーがXML文書を解析していく中で開始タグの出現や終了タグの出現をそれぞれイベントとして扱い、リスナー・プログラム中でそれぞれのイベントに応じた処理を行うものです。プル型はXML文書の読み込みをプログラム内で制御し、それぞれのノードに応じた処理を行うものです。LibXml-Rubyでは、機能の豊富さとプログラミングのしやすさからプル型のLibXML::XML::Readerを用いました。一方で、REXMLではPullパーサーは現時点APIドキュメント上に“This API is experimental, and subject to change.”と記載されており、まだ開発途上であるため、プッシュ型のSAX2をストリーミング・パーサーとして利用しました。DOMとストリーム処理の特徴および長所、短所は表 1に示すとおりです。

表1. DOMとストリーミング・パーサーの特徴
DOMストリーム処理
特徴XMLデータをツリー構造でメモリーに展開して扱うXMLデータの各行を順に読み込み処理を行う
長所
  • XMLツリー内を自在に移動できる
  • XPathが利用できる
  • XML文書の作成が容易
  • 各行単独で処理が完結するような場合には、シンプルなプログラムを書くことができる
  • メモリー消費が比較的少ない
  • パフォーマンスに優れる
短所
  • メモリーを大量に消費する
  • パフォーマンスに劣る
  • XMLツリー内を自在に移動するような処理ができない
  • XML文書の作成には向かない

パフォーマンス測定結果

上述の処理1および処理2における、各パーサーが要した処理時間を表2、表3に示します。なお、これらの測定は著者のノートPC上で実施しています。テストした環境は次の通りです。

  • OS : Windows XP
  • CPU : Core2Duo T7300 2.0GHz
  • Memory : 2GB
  • Ruby : Ruby 1.8.6
  • LibXml-Ruby : 1.1.3
表2. 処理1の処理時間
XMLライブラリーREXMLlibXML
パーサーDOMSAX2DOMReader
処理時間(東証)[s]0.650.940.070.05
処理時間(U.S. GAAP)[s]0.691.060.070.06

まず処理1(表2) について見てみましょう。単独のXML文書を扱い、必要な要素のデータを単に上から順に読み出すような処理において、DOMとストリーミング・パーサーを比較した場合、REXML、LibXMLいずれの場合もそれほど大きな違いは出ていません。特にREXMLにおいてはDOMよりむしろSAX2の方が時間が掛かっています。これは、今回の測定した時間の中にリスナーの生成時間も含めたためと考えられます。また、REXMLとLibXMLを比較すると、LibXMLの方がDOMにおいておよそ1/10、ストリーミング・パーサーにおいておよそ1/20の処理時間で済んでいます。たいていの業務においてはREXMLにより提供されるパフォーマンスで十分かもしれませんが、それにしてもLibXMLの方が高速に処理を実行できることが読み取れます。

表3. 処理2の処理時間
XMLライブラリーREXMLlibXML
パーサーDOMSAX2DOMReader
処理時間(東証)[s]894.3535.7326.161.53
処理時間(U.S. GAAP)[s]4750.8973.0294.242.81

続いて、処理2(表3)を見てみましょう。処理1同様にDOMとストリーミング・パーサーで比較すると、いずれのXMLライブラリーでもストリーミング・パーサーの方が大幅に短時間で処理を行うことができています。これらの例では、DOMの方が17~65倍の時間が掛かる結果となっています。また、REXMLとLibXMLで比較すると、DOMでは30~50倍程度、ストリーミング・パーサーでは25倍程度REXMLの方が処理時間が掛かっています。このようにより多くのXML文書を一連の処理の中で扱う必要があり、ここのXML文書の中でもより複雑な処理を行うことにすると、顕著に処理時間の差が現れてきます。

表4. それぞれのパーサーのメモリー使用量
XMLライブラリーREXMLlibXML
パーサーDOMSAX2DOMReader
最大メモリー使用(東証) [MB]10993112
最大メモリー使用(U.S. GAAP)[MB]275177117

さらに、この時のメモリーの使用量を表4から確認してみましょう。ストリーミング・パーサーに比べてDOMの方が3~10倍と大幅に大きなメモリーを必要とすることが分かります。また、DOMを利用する場合でもLibXMLに比べてREXMLの方がより多くのメモリーを必要としています。

まとめ

以上のことから、REXMLとLibXMLそれぞれが向いているシチュエーションをまとめると次のようになります。

REXML:

  • 簡単にXMLデータを扱う処理を試してみたい時
  • 一度に扱うXMLデータの数が少ない時
  • XMLデータに対する処理が簡単な時

LibXML:

  • 少しでもパフォーマンスを良くしたい時
  • 一度に複数のXMLデータを扱う時
  • XMLデータに対して複雑な処理が必要な時

また、今回の一連の作業で同様の処理を行うプログラムについてREXMLとLibXml-Rubyの間、およびDOMとReaderまたはSAX2の間でポーティングを行っています。そこから、DOM同士であればREXMLからLibXmlへの移行は思ったより簡単にできることが分かりました。またDOMからReaderへの移行も、ちょっとの手間はありますがそれほど難しくありませんでした。SAX2については、イベント処理型のコーディングとなるため、それなりにプログラムを書き換える必要がありました。


ダウンロード可能なリソース


関連トピック

  • REXML (US): REXMLのホームページです。REXMLについての概要を知ることができます。TutorialおよびAPI Docへのリンクもあります。
  • LibXml-Ruby (US): LibXml-Rubyのホームページです。LibXml-Rubyについての概要を知ることができます。API Docへのリンクもあります。API DocのREADMEに簡単な使い方が示されていて参考になります。
  • ヒント:軽量XMLライブラリー」(David Mertz, Ph.D著、developerWorks、2002年3月): REXMLを含むいくつかの軽量なXMLライブラリーについて紹介されています。
  • XMLの論考:REXMLライブラリー」(David Mertz, Ph.D著、developerWorks、2002年3月): REXMLについて紹介されています。DOMおよびストリーム・モードそれぞれのコーディング例が示されており、どのようにコーディングするのかの理解を助けます。
  • 東証:決算短信XBRLデータ」: 今回テストデータとして用いたXBRLのサンプル・データを入手できます。
  • XBRL U.S.: 2008 U.S. GAAP Taxonomies 1.0 (US)」: 上に同じく、今回テストデータとして用いたXBRLのサンプル・データを入手できます。
  • Rubyダウンロード」: Rubyを入手するためのさまざまな方法が説明されています。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management, XML, Open source
ArticleID=430677
ArticleTitle=性能かコーディング量か?RubyにおけるXMLライブラリーの選び方
publish-date=09242008