メインブログに書くまでもない自分用メモを垂れ流す
3年前に話題になった、Web::ScraperでXML::LibXMLを使うと爆速になる話(ttp://d.hatena.ne.jp/tokuhirom/20090324/1237904392)のWeb::Query版。
パーサをXML::LibXMLに取り替える機能がWeb::Scraper本家に加わる以前、
use HTML::TreeBuilder::LibXML;
HTML::TreeBuilder::LibXML->replace_original();
の2行を追加すればWeb::Scraperのコードに変更を加えずしてパーサをXML::LibXMLに取り替えることができ、HTMLの解析が爆速になる(速くなるのはXML::LibXMLがXSで書かれているから)という話だったけど、あれと同じことがWeb::Queryでもできるか試してみた。
HTML::TreeBuilder::LibXMLをWeb::Queryに使うにはHTML::TreeBuilder::LibXMLにいくらか実装を書き足す必要があったので、そこを書きたしたうえで、パーサの速度を測ってみた。(HTML::TreeBuilder::LibXMLのほうのテストがまだ全部通ってないのだけど、通ったら変更部分のコード上げます。すんません)
use HTML::TreeBuilder::LibXML use Path::Class qw(file); use Benchmark qw(cmpthese); use Filt; # ローカルに保存しておいた http://b.hatena.ne.jp/Cside/favorite のHTMLを取り出す my $html = file("$Bin/test/favorite.html")->slurp; # パース部分のコード: # https://github.com/Cside/Filt/blob/master/lib/Filt/Model/Feed.pm sub parse { Filt::Model::Feed->get($_[0]) } cmpthese(10, { no_libxml => sub { parse($html); }, use_libxml => sub { # パーサを入れ替える HTML::TreeBuilder::LibXML->replace_original(); parse($html); }, });
結果
s/iter no_libxml use_libxml
no_libxml 11.1 -- -95%
use_libxml 0.542 1953% --
19倍速くなった。
HTML::TreeBuilder::LibXMLのテストが全部通ったらpull reqする予定。
はてなからHTMLをスクレイピングしてきてパースしてRSSに出力するサービス(http://hbt.cside.me/)をこないだ作ったのだけど、とにかくレスポンス遅かった。
で、何に時間を食ってるのかプロフィアリングして内訳を見てみたら
| はてなからのレスポンス待ち | 3.0 sec |
| HTMLのパース | 2.5 sec |
| RSS形式で出力 | 0.5 sec |
という感じで、HTMLのパースにかかる時間が結構無視できない長さになっていた。
Webアプリケーションのボトルネックなんて大体I/O待ちでしょ、と予測していたけど、そうでもないようだった。計測やっぱり重要。