2112-09-03 おしらせ
■この日記にあるもの

わたしはだれ
サイドバーのプロファイルを見てください。
日常のつぶやきはTwitterに。
データベース
「アイドルマスター」タグ付き全動画情報データベースの更新状況と公開場所は「ニコニコ部の日記」です。
なお、データベース収集・分析のアイデアがありましたらお声をかけてください。
試験的にデータベースの更新をお知らせするRSSを出力しています。
http://aoineko.ciao.jp/nicodata.rss
GMスクリプト
Fast Look up NicoInfoは、マウス選択箇所やリンク先の動画情報(ニコニコ動画のもの)を表示します。
Pixiv Slideshowは、Pixivの「お気に入りユーザー新着イラスト」ページに“スライドショウ”を追加します。スライドショウでは「次へ」「前へ」のリンクを使って、イラストを見ることができます。
2011-12-31 シンデレラガールズの勢いをちょっと見てみる in pixiv
■[アイドルマスター][pixiv][perl][Mechanize][Scraper]シンデレラガールズの勢いをちょっと見てみる in pixiv

モゲマスのキャラがどれだけ流行ってるのかなーと思ったので、ざっとタグデータを拾ってみました。見ての通り、3つ以上出現したタグを一覧で。
perlのWWW::MechanizeとWWW::Scraperで小一時間ほどでした。スクリプトはこちら。
| タグ | 登場数 |
|---|---|
| アイドルマスターシンデレラガールズ | 180 |
| 双葉杏 | 37 |
| 三村かな子 | 32 |
| ぽっちゃり | 24 |
| 諸星きらり | 9 |
| 天海春香 | 8 |
| 小日向美穂 | 7 |
| 龍崎薫 | 6 |
| 上条春菜 | 6 |
| 島村卯月 | 6 |
| 巨乳 | 6 |
| 奥山沙織 | 6 |
| 前川みく | 6 |
| 神崎蘭子 | 5 |
| 萩原雪歩 | 5 |
| 川島瑞樹 | 5 |
| C81 | 5 |
| ナターリア | 5 |
| 福山舞 | 5 |
| 如月千早 | 4 |
| 水本ゆかり | 4 |
| 渋谷凛 | 4 |
| 中野有香 | 4 |
| 喜多見柚 | 4 |
| 柊志乃 | 4 |
| 我那覇響 | 4 |
| だいたいあってる | 4 |
| 星井美希 | 3 |
| 三船美優 | 3 |
| 双海真美 | 3 |
| 佐城雪美 | 3 |
| 赤城みりあ | 3 |
| 佐々木千枝 | 3 |
| 城ヶ崎莉嘉 | 3 |
| ふともも | 3 |
| ふとましい | 3 |
| 緒方智絵里 | 3 |
| 神谷奈緒 | 3 |
| 東郷あい | 3 |
| 響をいじめ隊 | 3 |
OK,時代はニートとぽっちゃりだ!
あと、何気に春香さん強い。そして響はいじめたいほどかわいい!
すでにC81というタグが見える当たり、みなさん行動が早いですね。冬コミ後にもっと変化が出るかも。
2011-03-30 CoroでFurl
■[perl][Coro][Furl]測ってみた

前回のエントリーブクマコメントに、id:gfxさんからCoroからFurlを使う方法を書いていただいていたので、同じ環境でベンチしてみました。
gfx++
Coro+Furlのコードはhttps://gist.github.com/665488から。
use strict; use warnings; use 5.0100; use Furl; use AnyEvent::HTTP; use Coro; use Coro::Select; use Coro::AnyEvent; use Coro::Semaphore; use Benchmark qw/timethese cmpthese/; # request my $url = 'http://ext.nicovideo.jp/api/getthumbinfo/'; my $retry = 3; open my $fh, '<:utf8', '_tmp'; my @list; for (0 .. 100) { my $line = <$fh>; chomp $line; push @list, $url . $line; } close $fh; cmpthese timethese 1, { CoroFurl => sub { my @coros; foreach my $url(@list) { chomp $url; push @coros, async { print "fetching $url\n"; my $furl = Furl->new(); my $res = $furl->get($url); print "$url: ", $res->status_line, "\n"; }; } $_->join for @coros; }, Coro => sub { my $sem = Coro::Semaphore->new(5); my @coros; for my $video_id (@list) { chomp $video_id; push @coros, async { my $guard = $sem->guard; http_get $video_id, Coro::rouse_cb; my ($data, $hdr) = Coro::rouse_wait; if ($hdr->{Status} =~ /^2/) { #print "finish, $hdr->{Status} $hdr->{Reason} $hdr->{URL}\n"; } else { warn "error, $hdr->{Status} $hdr->{Reason} $hdr->{URL}\n"; } }; } $_->join for @coros; }, };
で、結果。Furlは早いし、Coro::Select使うだけで簡単でいいですね。
Benchmark: timing 1 iterations of Coro, CoroFurl...
Coro: 22 wallclock secs ( 0.38 usr + 0.11 sys = 0.49 CPU) @ 2.06/s (n=1)
(warning: too few iterations for a reliable count)
CoroFurl: 8 wallclock secs ( 0.05 usr + 0.05 sys = 0.09 CPU) @ 10.64/s (n=1)
(warning: too few iterations for a reliable count)
Rate Coro CoroFurl
Coro 2.06/s -- -81%
CoroFurl 10.6/s 416% --
2011-03-28
■[perl][Furl][AnyEvent][Coro][ニコニコ動画]APIへの問い合わせを高速化したい

結論
Furlは非常に速い。でも、AnyEventの方が仕事が早く終わった。
今回は、相手サーバーが応答してデータを取得するまでの時間の方がボトルネック。
なお、結果として次の動画を作るのにとっても役に立った。
ときどきAEでAPI叩いているとエラーが返ってきましたけど。
背景
nicomas.sqlite用にデータを取得するperlスクリプトの実行に時間がかかっているのを何とかしたい。
135,000件以上の「アイドルマスター」タグのついた動画があるので、時間がかかるのはしょうがないけど、工夫できないだろうか。
なお、環境はstrawberry perl 5.12.1 built for MSWin32-x86-multi-threadをWindows XPで動かしています。
現状
一番時間がかかるのはタグ検索ページのスクレイピング。でもこれはニコニコ動画側の負荷を考えてウェイトをいれているし、これ以上早くする気は無い。
二番目がAPI問い合わせなので、ここを改善する。コードはだいたい下のとおり。
# もともとはLWPを使った、いたって普通のコード my $enc = Encode::find_encoding('utf8'); my $ua = LWP::UserAgent->new; for my $url (@urls) { my $res = $ua->get($url); if ($res->is_success) { my $content = $enc->decode('utf-8', $res->content); # do something } }
Furl編
参考情報とベンチマーク
にひりずむ::しんぷる - 初めての Furlを参考にした。
Kazuho’s Weblog: 5x performance - switching from LWP to Furl & Net::DNS::LiteのNet::DNS::Liteを使う方法は、Net::DNS::Liteが上手く動いてくれなかったので試していない。
さくっとベンチマークを取ってみた。実際に使うサブルーチンをコピペした。
なお、localhost:5000ではplackupでhttp://ext.nicovideo.jp/api/gettumbinfo/sm9のデータを返すように書いたpsgiを動かしている。
use strict; use warnings; use 5.0100; use Furl::HTTP; use LWP::UserAgent; use Benchmark qw/timethese cmpthese/; # setup vars my $timeout_in_seconds = 5; my $count = 1000; # create HTTP object my $furl = Furl::HTTP->new( timeout => $timeout_in_seconds, ); # create LWP object my $ua = LWP::UserAgent->new(); # request param my $url = 'http://localhost:5000/'; my $retry = 3; cmpthese timethese $count, { Furl => sub { furl_get($furl, $url, $retry); }, LWP => sub { lwp_get($ua, $url, $retry); }, }; sub furl_get { my ($furl, $url, $retry, $wait) = @_; $retry ? $retry += 1 : $retry = 1; $wait = 0 unless $wait; my ($minor_version, $status, $message, $headers, $content); while ($retry) { ($minor_version, $status, $message, $headers, $content) = $furl->request( method => 'GET', url => $url, ); if ($status == 200) { last; } else { $retry--; sleep $wait if $wait; } } return ($status, $content); } sub lwp_get { my ($lwp, $url, $retry, $wait) = @_; $retry ? $retry += 1 : $retry = 1; $wait = 0 unless $wait; my $res; while ($retry) { $res = $lwp->get($url,); if ($res->is_success) { last; } else { $retry--; sleep $wait if $wait; } } return ($res->code, $res->content); }
結果はこちら。
Benchmark: timing 1000 iterations of Furl, LWP...
Furl: 3 wallclock secs ( 0.78 usr + 0.48 sys = 1.27 CPU) @ 789.89/s (n=1000)
LWP: 6 wallclock secs ( 2.42 usr + 0.76 sys = 3.19 CPU) @ 313.77/s (n=1000)
Rate LWP Furl
LWP 314/s -- -60%
Furl 790/s 152% --
AnyEvent + Coro編
use strict; use warnings; use 5.0100; use Furl::HTTP; use AnyEvent::HTTP; use Coro; use Coro::AnyEvent; use Coro::Semaphore; use Benchmark qw/timethese cmpthese/; # 中略 open my $fh, '<:utf8', 'video_id_list.txt'; my @list; for (0 .. 100) { my $line = <$fh>; chomp $line; push @list, $url . $line; } close $fh; cmpthese timethese $count, { Furl => sub { for (@list) { furl_get($furl, $_, $retry) } }, Coro => sub { my $sem = Coro::Semaphore->new(5); my @coros; for my $video_id (@list) { chomp $video_id; push @coros, async { my $guard = $sem->guard; http_get $video_id, Coro::rouse_cb; my ($data, $hdr) = Coro::rouse_wait; if ($hdr->{Status} =~ /^2/) { #print "finish, $hdr->{Status} $hdr->{Reason} $hdr->{URL}\n"; } else { warn "error, $hdr->{Status} $hdr->{Reason} $hdr->{URL}\n"; } }; } $_->join for @coros; }, }; sub furl_get { my ($furl, $url, $retry, $wait) = @_; $retry ? $retry += 1 : $retry = 1; $wait = 0 unless $wait; my ($minor_version, $status, $message, $headers, $content); while ($retry) { ($minor_version, $status, $message, $headers, $content) = $furl->request( method => 'GET', url => $url, ); if ($status == 200) { last; } else { $retry--; #sleep $wait if $wait; } } return ($status, $content); }
AnyEvent::HTTPは同一ホストへのアクセスを4に制限しているので、セマフォで並列を5にする必要はなさそうです。ちょっとCoroを触ってみたかったので、上のようなコードになっています。
結果はこちら。
Benchmark: timing 1 iterations of Coro, Furl...
Coro: 24 wallclock secs ( 0.25 usr + 0.09 sys = 0.34 CPU) @ 2.91/s (n=1)
(warning: too few iterations for a reliable count)
Furl: 6 wallclock secs ( 0.08 usr + 0.08 sys = 0.16 CPU) @ 6.41/s (n=1)
(warning: too few iterations for a reliable count)
Rate Coro Furl
Coro 2.91/s -- -55%
Furl 6.41/s 121% --
ご覧の通り、Furlの方が処理は速いけど、AnyEvent::HTTPの方が全ての仕事をやり終えるのが早い。ローカルでデータをパースしたりするともっと差が出るようです。
検証が足りない気もするけど、自分の用途では役に立ったのでここまで。なお、データ収集スクリプトでの実戦投入はまだやってません。
2010-11-12 パスワード管理ソフトに悩む
■[software][Andoroid]Andoroid, Windows両対応パスワード管理ソフト

Galaxy Sを買って、iPod touchとWindows XPのデスクトップマシンとWindows 7のラップトップ、ついでにUbuntu入れたNetbookを持つ体制となりました。
そんなこんなでパスワード管理がめんどうなのでパスワード管理ソフトを比較検討してみた。
Lastpassはまたこんど。
| product | 1password | keepass |
|---|---|---|
| license | proprietary | OSS(GPL) |
| browser | Win: IE 7(32bit), Firefox 3(32bit) Mac: Safari 4, Firefox 3, Chrome(in progress) | IE(Unofficial), Firefox(Unofficial) |
| Apple | Mac, iPhone/iPad/iPod touch | Mac(Unofficial), iPhone/iPod touch(Unofficial) |
| Windows | OK(Beta) | OK |
| Andoroid | OK(Unofficial) | OK(Unofficial, readonly) |
| Other | - | Unofficial: Linux, BlackBerry, Palm, ... |

