Yokohama.pm #8 で cpanm + OrePAN についてプレゼンしてきました

去る 2011/11/18、Yokohama.pm #8 にて、プロジェクトで利用する CPAN モジュール群の部分ミラー(tarball のアーカイブ)を作りましょうという話をしました。

プレゼンの内容は、今回のプレゼン中でも1、2番目に簡単だった気がします。
本当は kazeburo さんの10ヶ月前の記事で十分なのですが、もっと(元が)参照されるべきかなと思ったので。
特に mac で作って linux で本番、なんて感じのサービスをやられている方には参考にしていただきたいです。

      • -

carton については、carton --bundle や cpanfile について少しでも意見を出せるようになってから発言したほうがよいなと思い、今回は控えさせていただきました。
ALPHA release のものを使う場合は fork & pull req する気持ちをもって使ったほうがよい。

雑感

angelos をヲチしております。

そういえば Makefile.PL で author_tests を使う場合、Module::Install::AuthorTests を requires か test_requires に含めないとちょっと困ったかもしれない。

ガンダム無双2にハマっています。

もっとだ、もっと、もっとこい!
シーブックが Lv.50 で、もう少しで親密40人。
YouTube 見ちゃうとムービーがゴロゴロ置いてあるけど見ない! 攻略 wiki も見ない。

remedie お試し中

どこかのブログで「 remedielinux のサーバが必要 」って書かれていた気がするけど、誤解を生んでそうだなぁと思いました。

ためいきとシリアライズ

キャッシュしよう
http://perl-users.jp/articles/advent-calendar/2008/23.html


残念ながらオリジナルのDateTimeよりも遅くなってしまいました。約半分の速度に落ちました。

わかってはいたことなんですが、このベンチマークは悔しい・・・
正直オブジェクトでのベンチは見て見ぬフリをしていました。っていうのがすでに甘いですね。

Method::Cached でパフォーマンス・チューニングする際の勘所は以下の2点かと思っていて、

  • データをシリアライズする際のコスト
    • キャッシュのストレージIFに依存する
    • ストレージが perl on memory な形であればまったく気にならない(単純なハッシュなど)
    • mod_perl で prefork な環境だった場合に、実行するプロセスによって値が違う
  • メソッドの呼び出し元のパラメータをシリアライズする際のコスト
    • 単純なスカラーの配列であれば連結するだけだが、$self のメンバメソッドだった場合に一気に面倒なことになる(現状はユーザー定義におまかせして逃げている

そのどちらにも悩まされていました。


中量級なクエリをキャッシュできればまぁいいかな、という想定が甘かったことを認識しました。。。
精進します。


ちなみに余談ですが、このモジュールのデフォルトでの組み込みは Cache::FastMmap になっていますが、実際に自分が使う際は Cache::Memcached( ::Fast )だったりするので無難なインターフェースとして get / set / delete or clear を選んでいます。



さらにさらに余談を言ってしまうと。
svn head では mod_perl でも無理やり動くようにしてみてました。
現状 CPAN にあげてあるものだと動いていなかったという事実。

最近困ってること

その package の BEGIN フェーズだと、シンボルテーブル作られてないんですね、、、

コードリファレンスから GV を取得しようとしても GV が得られず、B::SPECIAL なんてものが取れてしまう。

おかげでサブルーチン自身の名前がわからない、、、

ぼ、ぼすけて

初 shipit しました - Method::Cached

shipit した後念のため PAUSE を覗いてみたら、Upload Material に QRCode 系モジュールが三つ並んでました。

      • -

知らなかったのですが、shipit の Tags Hook を使えばリポジトリの proj/tags 以下にリリースバージョンを勝手に add してくれるんですね。
最強に便利だと思いました(いまさら)。

      • -

追記: CPAN Recent に反映されました。

Method-Cached-0.02
http://search.cpan.org/~boxphere/Method-Cached-0.02/

Method::Cached の ToDo は以下の通り:

  • POD が全然ダメ
    • SYNOPSIS が間違っている
      • 素直にテストをコピーすればよかったorz
      • もし少し使ってみようという奇特な方がいらっしゃいましたら、せめてテストの01〜03辺りをご覧になられるといいと思います…
    • デフォルトが Cache::FastMmap なことを書き忘れた。
    • SEE ALSO を書き忘れた、、もっと謙虚に><
  • キャッシュの delete メソッドを実装していない
      • -

あと、今日は TPFJ の飲み会に参加させてもらうことができたので、自分はあまりコアなことはわからないのですが、せめて Perl に対する思いを熱く語れればいいなぁと思いますm(_ _)m

Hook::BitMask

ふと個人的に欲しくなったので CodeRepos に上げました。
本気でこういう処理をしようと思ったら xs で書くのがいいと思った。

lang/perl/Hook-BitMask
http://coderepos.org/share/browser/lang/perl/Hook-BitMask/trunk


使い方はこんな感じです:

use Hook::BitMask (
    FLAG1 => sub { $_[0] .= 'hello ' }, # 0b0001
    FLAG2 => sub { $_[0] .= 'world ' }, # 0b0010
    FLAG3 => sub { $_[0] .= '!'      }, # 0b0100
);

{
    # 0b0111
    my $flag = FLAG1 + FLAG2 + FLAG3;

    # HOOK を実行するAPI、bitstrap
    bitstrap($flag, my $word1);

    is $word1, 'hello world !';
}


ベンチマークについて興味がありましたら以下をどうぞ。
http://coderepos.org/share/browser/lang/perl/Hook-BitMask/trunk/t/benchmark.pl

さすがに if-else や三項演算子と競争すると厳しいけど、そこそこ普通の速度感かなぁ。。

CodeReposに初アップ

今まで上げよう上げようと思っていて、なかなか上げられなかったのですが今日ようやく初アップしました。

lang/perl/Method-Cached
http://coderepos.org/share/browser/lang/perl/Method-Cached/trunk

テストの中途半端さもあったり、依存するモジュールが微妙に多かったりとまだまだ CPAN に上げられる品質ではない感じ。
使う必要のないデフォルトクラスのために Cache::FastMmap を必要としてしまう辺りはショボいのでこれから直します。

※2008/09/30、若干修正
試しにベンチマークもとったけどまだまだ遅い。

                     Rate C(FileCache) C(Memcached-Fast) C(FastMmap)     Memoize
C(FileCache)        917/s           --              -82%        -86%        -99%
C(Memcached-Fast)  5128/s         459%                --        -22%        -92%
C(FastMmap)        6536/s         612%               27%          --        -90%
Memoize           66667/s        7167%             1200%        920%          --

パラメータをシリアライズしてキャッシュキーに仕立て上げる辺りが富豪的だったりしているのでここも直す予定…

ちなみにテストに使用したコードはこちら。

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin::libs;

use Method::Cached::Manager -domains => {
    'cache-memcached-fast' => {
        storage_class    => 'Cache::Memcached::Fast',
        storage_args     => [
            { servers    => [qw/ 127.0.0.1:11211 /] },
        ],
    },
    'cache-fastmmap'       => {
        storage_class    => 'Cache::FastMmap',
        storage_args     => [
            share_file     => '/tmp/fastmmap.bin',
            unlink_on_exit => 0,
        ],
    },
    'cache-file'           => {
        storage_class    => 'Cache::FileCache',
    },
};

{
    package Dummy;

    use Method::Cached;
    use Attribute::Memoize;

    sub fib_memcached : Cached('cache-memcached-fast', 5) {
        my $n = shift;
        return $n if $n < 2;
        fib_memcached($n - 1) + fib_memcached($n - 2);
    }

    sub fib_fastmmap : Cached('cache-fastmmap', 5) {
        my $n = shift;
        return $n if $n < 2;
        fib_fastmmap($n - 1) + fib_fastmmap($n - 2);
    }

    sub fib_file : Cached('cache-file', 5) {
        my $n = shift;
        return $n if $n < 2;
        fib_file($n - 1) + fib_file($n - 2);
    }

    sub fib_memoize : Memoize {
        my $n = shift;
        return $n if $n < 2;
        fib_memoize($n - 1) + fib_memoize($n - 2);
    }
}

package main;

use Benchmark;

my ($mc_fib, $fm_fib, $f_fib, $m_fib);

sub mc_fib { $mc_fib = 10; $mc_fib = Dummy::fib_memcached($mc_fib) }
sub fm_fib { $fm_fib = 10; $fm_fib = Dummy::fib_fastmmap($fm_fib)  }
sub f_fib  { $f_fib  = 10; $f_fib  = Dummy::fib_file($f_fib)       }
sub m_fib  { $m_fib  = 10; $m_fib  = Dummy::fib_memoize($m_fib)    }

Benchmark::cmpthese(10000, {
    'C(Memcached-Fast)' => \&mc_fib,
    'C(FastMmap)'       => \&fm_fib,
    'C(FileCache)'      => \&f_fib,
    'Memoize'           => \&m_fib,
});