このあたりがよくまとまってました。
http://weblog.nqou.net/archives/20090223224328.html
PurePerlなFeedPPが結構頑張ってる印象。
自分で書いたSAXハンドラーがどんなもんか試した。
いろんなパーサーで。
Rate XML::Feed XML::RSS XML::SAX::PurePerl + ECH XML::LibXML::SAX + ECH XML::SAX::Expat + ECH XML::LibXML::SAX::Perser + ECH XML::RSS::LibXML + XML::Feed XML::RSS::LibXML XML::Feed 4.24/s -- -0% -25% -59% -75% -80% -83% -84% XML::RSS 4.25/s 0% -- -24% -59% -75% -80% -82% -84% XML::SAX::PurePerl + ECH 5.63/s 33% 32% -- -46% -67% -73% -77% -78% XML::LibXML::SAX + ECH 10.4/s 145% 144% 85% -- -38% -50% -57% -60% XML::SAX::Expat + ECH 16.9/s 298% 297% 200% 62% -- -19% -31% -36% XML::LibXML::SAX::Perser + ECH 20.9/s 393% 391% 271% 101% 24% -- -14% -20% XML::RSS::LibXML + XML::Feed 24.3/s 473% 471% 331% 134% 44% 16% -- -7% XML::RSS::LibXML 26.2/s 518% 516% 365% 152% 55% 25% 8% --
XML::RSSとXML::Feedが悲しいくらい遅いっぽい。
XML::RSS::LibXMLがかなり早い。
SAXではXML::LibXML::SAX::Perserがちょい優秀。ハンドラがダメ感があるけど。
XML::LibXML::SAX::PerserとXML::LibXML::SAXって何が違うんだろう。まぁいいか。
以下コード
use strict; use warnings; use 5.10.1; use Benchmark; use LWP::Simple; # 180KBぐらい。 my $XML_DATA = get("http://www.nicovideo.jp/ranking/view/monthly/all?rss=2.0"); Benchmark::cmpthese(100, { 'XML::RSS' => \&xml_rss, 'XML::RSS::LibXML' => \&xml_rss_libxml, 'XML::RSS::LibXML + XML::Feed' => \&xml_feed_libxml, 'XML::Feed' => \&xml_feed_default, 'XML::SAX::PurePerl + ECH' => \&xml_sax_pp, 'XML::SAX::Expat + ECH' => \&xml_sax_expat, 'XML::LibXML::SAX + ECH' => \&xml_libxml_sax, 'XML::LibXML::SAX::Perser + ECH' => \&xml_libxml_sax_parser, }); # XML::RSS::LibXML sub xml_rss_libxml{ use XML::RSS::LibXML; my @links; my $rss = XML::RSS::LibXML->new; $rss->parse($XML_DATA); for my $item (@{$rss->{items}}) { die if !$item->{link}; push @links, $item->{link}; } die if @links != 100; }; # XML::Feed sub xml_feed_default{ &xml_feed; } # XML::Feed + XML::RSS::LibXML sub xml_feed_libxml{ local $XML::Feed::Format::RSS::PREFERRED_PARSER = "XML::RSS::LibXML"; &xml_feed; }; sub xml_feed{ use XML::Feed; use XML::Feed::Format::RSS; my @links; my $feed = XML::Feed->parse(\$XML_DATA); for my $item ( $feed->items ) { die if !$item->link; push @links, $item->link; } die if @links != 100; } # XML::RSS sub xml_rss{ use XML::RSS; my @links; my $rss = XML::RSS->new; $rss->parse($XML_DATA); for my $item (@{$rss->{items}}) { die if !$item->{link}; push @links, $item->{link}; } die if @links != 100; }; # 自作ハンドラ(Expat) sub xml_sax_expat{ use XML::SAX; local $XML::SAX::ParserPackage = "XML::SAX::Expat"; &xml_sax; }; # 自作ハンドラ(LibXML) sub xml_libxml_sax{ use XML::SAX; local $XML::SAX::ParserPackage = "XML::LibXML::SAX"; &xml_sax; }; # 自作ハンドラ(XML::LibXML::SAX::Parser) sub xml_libxml_sax_parser{ use XML::SAX; local $XML::SAX::ParserPackage = "XML::LibXML::SAX::Parser"; &xml_sax; }; # 自作ハンドラ(XML::SAX::PurePerl) sub xml_sax_pp{ use XML::SAX; local $XML::SAX::ParserPackage = "XML::SAX::PurePerl"; &xml_sax; }; # 自作ハンドラ sub xml_sax{ use XML::SAX; use XML::SAX::ElementCallbackHandler; my @links; my $parser = XML::SAX::ParserFactory->parser( Handler => new XML::SAX::ElementCallbackHandler( element_callback => [ 'item' => sub{ my ($elem) = @_; die if !$elem->element('link'); push @links, $elem->element('link')->data; } ] ) ); $parser->parse_string($XML_DATA); die if @links != 100; }
どこか間違ってる気がしないでもない。