Perl モジュールの Coro のメモ書きです。
処理内容を見なおしたりキャッシュとか使ってみたりしながら、スクレイピング処理を効率的にできるように色々試しているのですが、その中で Coro というモジュールの存在を知ったので試してみました。
スクレイピング処理で一番時間がかかる部分はコンテンツを取ってくる所だと思うので、ここをマルチプロセス化と思いましたが、fork するよりはスレッドを使った方が省力化なのでこちらを採用。
まずは、RSS から個別記事の URL を抜き出してコンテンツを取得という処理を普通に書いてみます。
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use XML::FeedPP;
my $url = 'http://example.jp/feed';
my $res = &lwp_get($url);
my $feed = XML::FeedPP->new($res->content);
my @url = ();
foreach my $entry ($feed->get_item()) {
$res = &lwp_get($entry->link());
print $res->title, "\n";
}
sub lwp_get {
my $url = shift || return(0);
my $lwp = '';
my $res = 0;
$lwp = LWP::UserAgent->new(
timeout => 30
);
$res = $lwp->get($url);
if (!$res->is_success) {
$res = 0;
}
return($res);
}
exit;
これを自分のブログを使って実行するとこんな結果に。
# time perl lwp_get.pl PerlのLWPでCacheを使う | work.log PerlのCache::Fileが便利なのでメモ | work.log PerlからWordPressを操作する | work.log WordPressのwp_optionsテーブルって結構便利 | work.log PerlとかPHPで外部コマンドを実行した時の戻り値を判定する | work.log WordPressのstyle.cssに任意のバージョンを設定する | work.log WordPressで利用するファイルのExpiresヘッダを見直す | work.log WordPressで作ったコンテンツを最適化する試み | work.log WP Super Cache の手動インストールメモ | work.log WordPressでMinified化したstyle.min.cssを使う | work.log ----- 0.343u 0.087s 0:05.99 7.0% 10+5348k 0+0io 0pf+0w
実行時間は 5.99sec でした。
次は、同じ処理を Coro を使って並行化してみます。
#!/usr/bin/perl
use strict;
use warnings;
use Coro;
use Coro::LWP;
use LWP::UserAgent;
use XML::FeedPP;
my $url = 'http://example.jp/feed';
my $res = &lwp_get($url);
my $feed = XML::FeedPP->new($res->content);
my @result = ();
my $lock = Coro::Semaphore->new(5);
foreach my $entry ($feed->get_item()) {
push @result, async {
my $guard = $lock->guard;
$res = &lwp_get($entry->link());
print $res->title, "\n";
};
}
$_->join for @result;
sub lwp_get {
my $url = shift || return(0);
my $lwp = '';
my $res = 0;
$lwp = LWP::UserAgent->new(
timeout => 30
);
$res = $lwp->get($url);
if (!$res->is_success) {
$res = 0;
}
return($res);
}
exit;
まだ良く理解していない部分が多いですが、async で囲んだ部分がマルチスレッド化されて処理されるようになり、Web サーバの負荷を考慮して Coro::Semaphore で同時に処理するスレッド数を 5 に制限しています。
有り難いことに、Coro::LWP をロードするだけで LWP の待ち時間をなるべく無くするように勝手に処理してくれるみたいです。
先ほどと同様に自分のブログで試してみます。
# time perl lwp_coro.pl PerlとかPHPで外部コマンドを実行した時の戻り値を判定する | work.log PerlのLWPでCacheを使う | work.log PerlのCache::Fileが便利なのでメモ | work.log WordPressのwp_optionsテーブルって結構便利 | work.log PerlからWordPressを操作する | work.log WordPressで利用するファイルのExpiresヘッダを見直す | work.log WP Super Cache の手動インストールメモ | work.log WordPressのstyle.cssに任意のバージョンを設定する | work.log WordPressでMinified化したstyle.min.cssを使う | work.log WordPressで作ったコンテンツを最適化する試み | work.log ----- 0.403u 0.177s 0:03.59 15.8% 10+7126k 0+0io 0pf+0w
実行時間は 3.59sec と先ほどに比べて早く処理が完了しました。
表示されたタイトルの順番が先ほどと違うのを見ると、各リクエストが並行で行われたのが良くわかると思います。
とりあえず、何とか理解している範囲はここまで。
暫くは勉強も兼ねて Coro を使って色々試してみようと思います。