July 11, 2004

Perl で XML の処理はどれが速いかベンチ

[ Perl , XML ]

ある書籍の監訳作業をやっていて Perl と XML に関するところを読んでたら、ある疑問が沸々と。

RSS や OPML、changes.xml といった XML ドキュメントからある特定の要素だけを抜き出す処理はよくやります。例えば RSS に記載された permalink の URL を抽出して、それらを巡回などなど。

この特定の要素のみ抜き出すという処理の方法はいわゆる TMTOWTDI というやつで、いろいろやり方があります。正規表現、XML::ParserXML::LibXML + XPath などなど。で、速度的にはどんなもんなんだろう? と気になったのでベンチマークを取ってみます。

処理内容は、あらかじめ保存しておいた RSS ファイル (FeedBack で '加藤ローサ' の RSS) から、各エントリの permalink の URL を抜き出すというもの。この処理を、

1. 正規表現でぶっこ抜き
2. XML::Simple でパースして得られるデータ構造から取得
3. XML::RSS でパースして取得
4. XML::LibXML の DOM に対する XPath インタフェースで取得

の 4 とおりで行って、Benchmark モジュールで比較します。

予想では正規表現が一番速く、次に XML::LibXML、そして XML::Parser を内部で使用している 2. と 3. は同じくらいといったところ。

で、以下のスクリプトを書いて実行してみました。

#!/usr/local/bin/perl
 
use strict;
use warnings;
use Benchmark;
use FileHandle;
use XML::LibXML;
use XML::RSS;
use XML::Simple;
 
my $rss_file = shift or die "usage $0 \n";
my $fh = FileHandle->new($rss_file)
    or die "cannot open $rss_file: $!";
local $/; # slurp mode
our $content = $fh->getline;
$fh->close;
 
Benchmark::timethese(1000, {
    'regexp' => \&with_regexp,
    'XML::Simple' => \&with_xml_simple,
    'XML::RSS' => \&with_xml_rss,
    'XML::LibXML' => \&with_xml_libxml,
});
 
sub with_regexp {
    my $pattern = "<item .*?>.*?<link>(.*?)</link>.*?</item>";
    my @links =
	($content =~ m/$pattern/smg);
}
 
sub with_xml_simple {
    my @links = ();
    my $parser = XML::Simple->new;
    my $data = $parser->XMLin($content, ForceArray => 1);
    for my $item (@{$data->{item}}) {
	push @links, $item->{link}->[0];
    }
}
 
sub with_xml_rss {
    my @links = ();
    my $rss = XML::RSS->new;
    $rss->parse($content);
    for my $item (@{$rss->{items}}) {
	push  @links, $item->{link};
    }
}
 
sub with_xml_libxml {
    my @links =();
    my $parser = XML::LibXML->new;
    my $doc = $parser->parse_string($content);
    my @nodes = $doc->findnodes(
	"//*[local-name()='item']/*[local-name()='link']/text()"
    );
    for my $node (@nodes) {
	# print $node->nodeValue, "\n";
	push @links, $node->nodeValue;
    }
}

1 〜 4 の処理をそれぞれサブルーチンに分けて、Benchmark モジュールの timethese 関数に渡しています。サブルーチンの実行回数はそれぞれ 1000 回で。すべてのサブルーチンの処理結果は同じです。

あんま関係ないですが、省略された名前空間を持つエレメントを XPath で指定するのって結構めんどくさいですね。はまりました。@IT 会議室にて解答を発見。*[local-name()='item']とかなんとかやる必要ありでちょっと嫌んな感じです。

さて、ベンチマーク実行。

[naoya@judy XML-Bench]$ perl rss.pl sample.rdf
Benchmark: timing 1000 iterations of XML::LibXML, XML::RSS, XML::Simple, regexp...
XML::LibXML:  2 wallclock secs ( 1.77 usr +  0.00 sys =  1.77 CPU) @ 564.97/s (n=1000)
  XML::RSS: 93 wallclock secs (91.89 usr +  0.06 sys = 91.95 CPU) @ 10.88/s (n=1000)
XML::Simple: 372 wallclock secs (358.27 usr +  0.12 sys = 358.39 CPU) @  2.79/s (n=1000)
    regexp:  0 wallclock secs ( 0.13 usr +  0.00 sys =  0.13 CPU) @ 7692.31/s (n=1000)
            (warning: too few iterations for a reliable count)

圧倒的に正規表現が速い。「1000 回じゃ信頼性のある結果にはなりませんよ」とまで言われるします。XML::LibXML も思ってたよりかなり速いです。XML::RSS や XML::Simple よりも圧倒的。一方、同じ XML::Parser の XML::RSS と XML::Simple ですが、予想してたより結構差がつきました。4倍ぐらい。XML::Simple の解析ルーチンがかなり柔軟性に富んでるので、それなりのオーバーヘッドがあるんでしょうね。

正規表現が速いのは分かりましたが、汎用性やコードの保守性という点も考慮するとこの類の処理を大量に行うプログラムでは XML::LibXML + XPath がバランスが取れてて良さそうです。逆に Quick Hack なら正規表現かな。

ここまで差が付くとは思わなかったので、ベンチしてみて良かったです。

ちなみに使用したマシンのスペックは Pentium 4 2.80GHz (Hyper Threading 有効)のメモリが 1GB といったものです。

Posted by naoya at July 11, 2004 07:56 PM | トラックバック (8)  b_entry.gif
トラックバック [8件]
TrackBack URL: http://mt.bloghackers.net/mt/suck-tbspams.cgi/1114
Perl での RSS 処理ベンチ
Excerpt: FeedBack の開発者の方がつけている NDO::Weblog で面白いベンチが取り上げられていたのでメモメモ。 RSS の中から特定の要素を抜き出す方法は色々あるわけですが、その中でどの方法がもっとも早いのか?っていうテスト。結果は、正規表現の模様。Web ベースの RSS リーダ...
Weblog: Ceekz Logs
Tracked: July 11, 2004 11:35 PM
XML::Simple の処理はとても遅い
Excerpt: 最近 Perl で XML を処理することがとっても多いですね。Amazon Search の高速化のためいろいろデータを取得してみたら、XML::Simple...
Weblog: Drk7jp
Tracked: July 24, 2004 10:49 AM
PerlでRSSの処理のベンチマーク
Excerpt: NDO::WeblogさんのPerl で XML の処理はどれが速いかベンチで、正規表現、XML::Simple、XML::RSS、XML::LibXMLの4つ...
Weblog: blog.nomadscafe.jp
Tracked: August 3, 2004 11:40 AM
XML::LibXMLを用いてRSSファイルからデータをゲットする方法
Excerpt:  今日は1日、TSJのPerlスクリプトの改造ばっかりやっていました(←バカ)。  登録サイトでRSSのURIを指定していれば、RSSファイルをゲットしてサマ...
Weblog: TSJ付゛録゛
Tracked: August 8, 2004 10:01 PM
XML::LibXML、ってかDOM2 ('A`)マンドクセ。。。
Excerpt: Perl で XML の処理はどれが速いかベンチ : NDO::Weblog ...
Weblog: First Weblog
Tracked: March 23, 2005 10:28 AM
XML::LibXMLとXML::RSSでベンチ(今更ですが)
Excerpt: 昨日はマンドクセとかってネガな発言をしてしまったわけですが。 XML::Lib...
Weblog: First Weblog
Tracked: March 23, 2005 03:39 PM
[XML]PerlでXMLを操作する
Excerpt: [http://www.drk7.jp/MT/archives/000530.html:title] XML::Simple と XML::LibXML で...
Weblog: iRSSの日記
Tracked: October 17, 2005 03:53 PM
[XML]PerlでXMLを操作する
Excerpt: [http://www.drk7.jp/MT/archives/000530.html:title] XML::Simple と XML::LibXML で...
Weblog: iRSSの日記
Tracked: October 17, 2005 03:53 PM
コメント [0件]
コメントする









名前、アドレスを登録しますか?