RSSのパース速度の比較

色々と触発されてやってみた。 参考: Perl で XML の処理はどれが速いかベンチ : NDO::Weblog iandeth. - XML::Simple は遅い説における意外な落とし穴 XML::Simple におけるパーサーの実行速度比較 - naoyaのはてなダイアリー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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ファイルを適宜用意してください。

ソースコード

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
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;
}

Comments

comments powered by Disqus