色々と触発されてやってみた。
参考:
Perl で XML の処理はどれが速いかベンチ : NDO::Weblog
iandeth. - XML::Simple は遅い説における意外な落とし穴
XML::Simple におけるパーサーの実行速度比較 - naoyaのはてなダイアリー
Benchmark: running XML::FeedPP, XML::LibXML, XML::RSS, XML::RSS::LibXML, XML::RSS::Parser, XML::RSSLite, XML::Simple, regexp for at least 3 CPU seconds...
XML::FeedPP: 2 wallclock secs ( 3.02 usr + 0.00 sys = 3.02 CPU) @ 55.37/s (n=167)
XML::LibXML: 3 wallclock secs ( 3.25 usr + 0.02 sys = 3.27 CPU) @ 496.02/s (n=1620)
XML::RSS: 4 wallclock secs ( 3.27 usr + 0.00 sys = 3.27 CPU) @ 2.76/s (n=9)
XML::RSS::LibXML: 4 wallclock secs ( 3.25 usr + 0.00 sys = 3.25 CPU) @ 49.54/s (n=161)
XML::RSS::Parser: 3 wallclock secs ( 3.19 usr + 0.00 sys = 3.19 CPU) @ 3.76/s (n=12)
XML::RSSLite: 3 wallclock secs ( 3.14 usr + 0.00 sys = 3.14 CPU) @ 112.10/s (n=352)
XML::Simple: 3 wallclock secs ( 3.14 usr + 0.00 sys = 3.14 CPU) @ 61.13/s (n=192)
regexp: 4 wallclock secs ( 3.28 usr + 0.00 sys = 3.28 CPU) @ 6340.14/s (n=20802)
Rate XML::RSS XML::RSS::Parser XML::RSS::LibXML XML::FeedPP XML::Simple XML::RSSLite XML::LibXML regexp
XML::RSS 2.76/s -- -27% -94% -95% -95% -98% -99% -100%
XML::RSS::Parser 3.76/s 37% -- -92% -93% -94% -97% -99% -100%
XML::RSS::LibXML 49.5/s 1697% 1216% -- -11% -19% -56% -90% -99%
XML::FeedPP 55.4/s 1909% 1371% 12% -- -9% -51% -89% -99%
XML::Simple 61.1/s 2118% 1524% 23% 10% -- -45% -88% -99%
XML::RSSLite 112/s 3967% 2878% 126% 102% 83% -- -77% -98%
XML::LibXML 496/s 17894% 13078% 901% 796% 711% 342% -- -92%
regexp 6340/s 229906% 168336% 12698% 11350% 10272% 5556% 1178% --
読み込んだRSSファイルは、「はてなブックマーク - タグ - 石原さとみ(タグ「石原さとみ」を含む新着エントリー)」な感じの20件です。
正規表現はパターンがちがちで応用は利きませんが、速さはピカイチ。
XML::LibXMLはXPathがよくわからないのでアレですが、使いこなせれば速さも申し分なしです。
XML::RSSLiteが結構頑張っている印象ですね。関数呼び出しなのが、この中では違和感ありますが。
XML::Simpleのパーサーは、無難にXML::Parserを指定することでそれなりに速いです。ただ、手元の環境だとXML::SAX::ExpatXSが最速だったのですが。
ま、環境によるんでしょうね
。
XML::FeedPPがかなり健闘していると思います。ファイル構成もシンプル(1枚だけ)だし、汎用性もあるし、レンタルサーバーにも最適でしょうね。
これからRSSなどを扱うならXML::FeedPPが便利でしょうね。
ソースコードは以下のとおり。
使う場合はRSSファイルを適宜用意してください。
ソースコード
use strict;
use warnings;
use Data::Dumper;
use Benchmark qw(:all);
use FileHandle;
use XML::LibXML;
use XML::RSS;
use XML::Simple;
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
use XML::RSS::LibXML;
use XML::RSS::Parser;
use XML::FeedPP;
use XML::RSSLite;
my $rss_file = "../satomi.xml";
my $fh = FileHandle->new($rss_file)
or die "cannot open $rss_file: $!";
local $/; # slurp mode
our $content = $fh->getline;
$fh->close;
cmpthese(timethese(0,
{
'regexp' => \&with_regexp,
'XML::Simple' => \&with_xml_simple,
'XML::RSS' => \&with_xml_rss,
'XML::LibXML' => \&with_xml_libxml,
'XML::RSS::LibXML' => \&with_xml_rss_libxml,
'XML::RSS::Parser' => \&with_xml_rss_parser,
'XML::FeedPP' => \&with_xml_feedpp,
'XML::RSSLite' => \&with_xml_rsslite,
}));
sub with_xml_rsslite {
my @links = ();
my %result;
parseRSS(\%result, \$content);
for my $item (@{$result{item}}) {
push @links, $item->{link};
}
# print Dumper \@links;
}
sub with_xml_feedpp {
my @links = ();
my $feed = XML::FeedPP->new($content);
foreach my $item ( $feed->get_item() ) {
push @links, $item->link;
}
# print Dumper \@links;
}
sub with_xml_rss_parser {
my @links = ();
my $parser = XML::RSS::Parser->new;
my $feed = $parser->parse_string($content);
foreach my $item ( $feed->query('item') ) {
push @links, $item->query('link')->text_content;
}
# print Dumper \@links;
}
sub with_regexp {
my $pattern = "<item .*?>.*?<link>(.*?)</link>.*?</item>";
my @links =
($content =~ m/$pattern/smg);
# print Dumper \@links;
}
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];
}
# print Dumper \@links;
}
sub with_xml_rss {
my @links = ();
my $rss = XML::RSS->new;
$rss->parse($content);
for my $item (@{$rss->{items}}) {
push @links, $item->{link};
}
# print Dumper \@links;
}
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) {
push @links, $node->nodeValue;
}
# print Dumper \@links;
}
sub with_xml_rss_libxml {
my @links = ();
my $rss = XML::RSS::LibXML->new;
$rss->parse($content);
for my $item (@{$rss->{items}}) {
push @links, $item->{link};
}
# print Dumper \@links;
}


コメントする