2009年04月25日

そんなわけで帰り道にある檜町公園のトイレにやって来たのだ

木曜日は天気も良いので昼飯を食べた後に全裸公園に行ってきました。


そんな訳でトイレにやってきたのだ


深夜のご利用はご遠慮下さい


この公園で唯一ある芝生広場です。自宅のようにくつろぐのはギリギリセーフかな?



この、のどかな公園を紹介する事が最近のテレビの流行なんでしょうか?
こちらの皆さんはお散歩中のワンちゃん達の邪魔にならないようにとか踏まないように気を使ってて大変そうでした。


TBSさんだけ物々しい警備スタッフ連れてきてました。まぁ平和な公園だったので出番なく暇そうでしたが。流石に警備行動し始めたら芝生の仲間の迷惑なんじゃないすかねー


この公園は自然豊かでとても良い感じでしたねー。昼休み中の人達がいっぱいくつろいでました。


良い感じの東屋もあったり。これじゃぁ自宅気分ですねー


昨日はミッドタウン側で農家直売的なのがあって行ってきたけど、ジャニーズ事務所上空にヘリコプターぐるぐる回ってて、直売の客のおばちゃん達が五月蝿い煩いとヘリに怒ってましたね。火事でもあったのでしょうか?(消防車いなかったけど)

Posted by Yappo at 10:29 | Comments (0) | TrackBack

2009年04月24日

TokyoCabinetがPerlのHASHより遅いわけがない!

こんにちわ!金曜日担当・Shibuya内フェアリーことYappoです。

mixi Engineers’ Blog » PerlとRubyで省メモリなハッシュを使おうにて

100万件のレコードを格納した場合のメモリ使用量と処理時間を測ってみましょう。Perl(5.8.8)でテストコードを動かしたところ、以下の改善が確認できました。標準のハッシュに比べて、メモリ使用量がTCのオンメモリハッシュだと約61%、TCのオンメモリツリーだと約37%になることがわかります。処理時間に関しては157%ほどになっていますが、まあ許容範囲ですよね。
といった事が書かれており、その文面の上の解説で、tieしたので、tieしてるからおせーんじゃねーの?とテストコードも見ないで呟いてたらmikioさんからtie使わないでやってるよ!とつっこんでいただきました

でもまぁ腑に落ちない所もあり「mikio wareがperlのhashより遅いわけが無い!」と思いながらもshibuya.pmとかあって放置してたのですが、OpenFrepaカンファレンスも終わったのでTokyoCabinet.pmの実装を見てみたら、引数の値チェックをpure perlでやりつつXSのコードを呼んでいる実装でした。
引数の値チェックは置いといて、Perlと言うのは関数呼び出しのコストが馬鹿に出来ないので、試しにXSの関数を直接呼ぶように書き換えてベンチマークを取ってみました。

以下結果で、hashが元のテストコードで言う所のPerlのハッシュの実装で、tc_mikioがmikioさんのTCを使った実装で、tc_yappoが今回XSを直接呼ぶようにしてみた実装です。

$ perl ./benchmark.pl 
             Rate tc_mikio     hash tc_yappo
tc_mikio 333333/s       --     -29%     -52%
hash     469484/s      41%       --     -32%
tc_yappo 694444/s     108%      48%       --
=== ちゃんとkey/valueが入ってるか見るよ at ./benchmark.pl line 41.
hash : 00222791 => h00222791 at ./benchmark.pl line 43.
mikio: 00222791 => m00222791 at ./benchmark.pl line 44.
yappo: 00222791 => y00222791 at ./benchmark.pl line 45.
やっぱりTokyoCabinetの方が断然高速ですね!mikio++

以下ベンチマークスクリプトです

#!/usr/bin/perl
use strict;
use warnings;
use blib;
use Benchmark 'cmpthese';

use TokyoCabinet;

my $runnum = 1000000;
my $tc_args = sprintf('*#bnum=%d#mode=wct#xmsiz=0', $runnum);

my %hash;

my $mikio_db = TokyoCabinet::ADB->new;
$mikio_db->open($tc_args) || die 'mikio open failed';

my $yappo_db = TokyoCabinet::adb_new();
TokyoCabinet::adb_open($yappo_db, $tc_args) or die 'yappo open failed';

my($hash_i, $mikio_i, $yappo_i) = (0, 0, 0);
cmpthese(
    $runnum, {
        hash => sub {
            my $buf = sprintf('%08d', $hash_i);
            $hash{$buf} = 'h'.$buf;
            $hash_i++;
        },
        tc_mikio => sub {
            my $buf = sprintf('%08d', $mikio_i);
            $mikio_db->put($buf, 'm'.$buf);
            $mikio_i++;
        },
        tc_yappo => sub {
            my $buf = sprintf('%08d', $yappo_i);
            TokyoCabinet::adb_put($yappo_db, $buf, 'y'.$buf);
            $yappo_i++;
        }
    }
);

warn "=== ちゃんとkey/valueが入ってるか見るよ";
my $key = sprintf('%08d', int(rand($runnum)));
warn "hash : $key => " . $hash{$key};
warn "mikio: $key => " . $mikio_db->get($key);
warn "yappo: $key => " . TokyoCabinet::adb_get($yappo_db, $key);

$mikio_db->close;
TokyoCabinet::adb_close($yappo_db);

結論としてはTokyoCabinet.xsにid:gfxパワーが加わると(xsの中で引数チェックとかするの意)とんでもない速度になりそうです。

Posted by Yappo at 14:02 | Comments (1) | TrackBack

2009年04月23日

Shibuya.pm #11で発表しました

こんにちは、本日のHOTEL担当、素敵なレディーことYappoです。3人の荷物が家族のオモチャにされないか心配だけどもう寝るぞ!話は変わるけど、acotieさんはアクメアクメ言っててどんだけアクメ好きなんだよ!と思ったのは内緒だぞ!

という訳でShibuya.pmで発表してきました。二本立てです。

一本目は、一般的なperl userの作法のBやらDevel::Peekの紹介に加えて、新しく作ったDevel::RunOpsAnalizeを使ってOPCODEの実行単位でPerlの動作を覗き見る方法の紹介をしました。

二本目はLTで、dan the eval botの作り方を説明する為のCentOSのインストールをするというのを口実にHatetterのアーキテクチャや、なぜこれらの要素を採用したかを紹介しました。
もちろんCentOSのインストールもCobblerとKoanのお陰で完了して、local::libでdan the eval botに必要なperlモジュールも楽々installできるとか嘘つきながら、3分クッキングメソッドで無事にirc botもirc serverにjoinする所までLTの限られた時間の中でデモできました。
LTの中で二つの題材を同時進行で発表するメソッドは案外使えるんだなと思いましたね。30秒オーバするポカやらかしたけど。

ちなみにnon-blockingとか言いましたが、実際にはmemcachedやらQ4Mの処理でblockは発生します。が、気にしなくても良い程度のblockです。maybe

資料は、http://svn.coderepos.org/share/docs/yappo/20090422-shibuyapm11から適当に辿って下さい。VMのサンプルスクリプトもありますよ。
Devel::RunOpsAnalizeはhttp://github.com/yappo/p5-devel-runopsanalyze/tree/masterから
LTのサイトのソースコード一式はhttp://github.com/yappo/website-hatetter/tree/masterからどうぞ。

関係無いけど、英語が出来ない,OCamlがわからない,etc etc etcなどと言ったくだらない理由で、そういう自分が苦手だとかいうのから遠ざかるのは馬鹿だなーと思ったなー。僕なんて相変わらず英語でコミュニケーション取るのがXS書くのより大変だけど、なぜか俺の横で海外組の二人が寝てるよ。起こしかたとか朝飯とかどうすりゃいいんだかわからんけど。

あーあとhidekさんのスター画像作んなきゃ

Posted by Yappo at 02:26 | Comments (0) | TrackBack

2009年04月16日

はてなのお気に入りアンテナをTwitter Clientで見れるゲートウェイ「Hatetter」作りました

注意:ブックマークだけでなく、お気に入りアンテナのフィードを使うようになりました。

はてブのお気に入りリストってRSSリーダとかで見たりするのが多いんですが、もっとTwitterのようにカジュアルにウオッチしたいと思って、お気に入りリストのRSSをTwitter API互換のFeedに変換するサーバを書きました。

Hatter - 太っ腹にソースコードも公開してるので、自宅サーバとかに置いて使うってのもできます。

たとえばid:acotieがお気に入りに入れてる人達のブックマークをTwitter風に変換したい時は

http://hatetter.blogdb.jp/acotie/statuses/friends_timeline.json
もしくは
http://hatetter.blogdb.jp/acotie/statuses/friends_timeline.xml
を使います。一回目アクセスした時は空ですが、1分くらい立つとFeedが出来てきます。
このままだとXMLやらJSONがそのまま出てくるので、何かしら専用くらいんとから見ると良いです。

XMLとJSONに変換するので、たいがいのクライアントで見れるようになるんじゃないかなぁと期待しています。

技術的補足

Hatterでは、Perl以外にもQ4Mとmemcachedを使っています。

最初リクエストがあった時には、空の結果を返しつつQ4Mにキューを詰んで、数十秒後にQ4MのWorkerがFeedを取りに行って、Feedの変換を行い、結果をmemcachedに積み込んでいます。
で、クライアントからの二度目のアクセスの時にはmemcachedに入っている変換結果を出すだけです。
一度キューに突っ込んだらmemcachedに時間を保存しておいて5分以内は、キューに突っ込まれないようにしています。
と言った事を、一つのID毎に行っているので大量のアクセスが来たとしても自分のサーバも、はてなのサーバも大変な事にならない予定です。
Webアプリとしてはmemcachedとmysql(Q4M)との間でしか通信しないので、殆どブロックする事無く高速に応答出来るのではないかと思っています。
また、大量に使われる事になってキューがいっぱいたまってもQ4MなのでFeedの処理で過負荷になることも無くて安心です。やばければworkerのプロセス増やせば良いだけですしね。

キューに関しても3回retryして失敗したらキューを捨てるという事をやっていて、これもData::Model::Driver::Queue::Q4Mのお陰で簡潔に実装が行われています。
Queue::Q4Mとは違って、queue_waitに渡すテーブルに対するコールバックハンドラを渡す感じになっていたり、queue_endやqueue_abortの面倒見なくても良い、また対応するqueueのレコードを予め取得してobjectにしてコールバックハンドラに返す。といった事が効いていると思います。Q4M可愛いよQ4M。

Web周りに関しては、普通にHTTP::EngineとMouseだけでやってます。FrameworkなんかこのレベルだといらなくてHTTP::Engineだけで事足りますわね。
あ、index.htmlだけHTTP::Engine::Middleware::Staticで出してますよ。

ということで、どうぞご利用下さい。

Posted by Yappo at 13:41 | Comments (1) | TrackBack

2009年04月13日

Q4MをMacPortsのMySQL環境に入れる方法

macportsでmysql入れると /opt/local/lib/mysql5/mysql とかいう独創的な所にライブラリが入るので、そのまんまのQ4Mのconfigureじゃ./configureすら上手く動かないし、ググっても良くわからないのでてっとり早くconfigure.inを書き換えたよ。

パッチはhttp://gist.github.com/94339から
実行令とかは下記の通り。

 $ patch < ../for-macports.patch
 $ autoconf
 # include ディレクトリを追加するのが必要
 $ CPPFLAGS=-I/opt/local/include ./configure --with-mysql=/opt/local/var/macports/sources/rsync.macports.org/release/ports/databases/mysql5-devel/work/mysql-5.1.33 --with-mysql_config=/opt/local/bin/mysql_config5

という感じで--with-mysql_configオプションを追加してmysql_configにライブラリパスとかの解決を行わせています。

あとはsudo port install boostとかするの忘れなければはまらない予定。

installおわったら

 $ mysql5 -u root < support-files/install.sql
して、気が向けば perl ./run_tests.pl してチェックすれば無事install完了です。

添削ありましたら、ご指摘くだしあ。

どうでも良いけどQueue::Q4Mのテストデータベースのデフォルトは q4m_test じゃなくて test_q4m が良い。なぜならば mysqld の初期設定で test_% ってのはテスト用として権限設定されてるから。
僕はtest_q4m作って

 $ Q4M_DSN=test_q4m make test 
しました。

Posted by Yappo at 19:22 | Comments (0) | TrackBack

2009年04月09日

mixiアプリ開発者デビューしてみた

さっそくアプリを登録したhttp://platform001.mixi.jp/run_appli.pl?id=814 デビュー申請とか言うのもしてみた。 内容はmixiのデペロッパ登録のやり方がとてもわかりずらかったので、皇族の人達が登録につまづかないように新設丁寧に登録の道筋を伝えるマニュアルになっています。
Posted by Yappo at 12:33 | Comments (5) | TrackBack

2009年04月02日

Safari3のメモリ管理が何か変?

今のところSafari3限定 (確認したのはバージョン 3.2.1 (5525.27.1))なのだが、IMGタグを追加したりremoveしまくってたりすると、どんどん使用メモリが増えてくる現象を発見した。
Safari4のβ版やらFirefoxではそういった事にならないのは確認したが、単純なDOM操作なのにもりもりメモリを使って行く。
ウインドウを閉じてもメモリは解放されずに、解放しなかったメモリは内部的に再利用してるっぽい。
で、閉じる前に確保してたメモリ領域を使い切ったっぽいポイントでまたメモリをもりもり食べ出す。
まるでメモリプールみたいな感じなんだがウインドウを閉じるまで再利用されてない感じなんだ。

ちなみにSRC属性を指定しないとメモリがもりもり増えなかったりする。

以下のHTMLをローカルに保存して、保存した所と同じディレクトリにdummy.pngという適当な画像を置いてからブラウザで開いて下さい。
メモリが増える様子はアクティビティモニタ等で見るとわかり易いでしょう。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
    <title>memory leak test</title>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="content-script-type" content="text/javascript">

    <script>
        var count = 0;
        var is_run = true;

        var $ = function(id){
            return document.getElementById(id);
        };

        var reload = function(){
            var container = $("container");
            while (container.childNodes.length > 0) {
                container.removeChild(container.childNodes[0]);
            }
            add();
        };

        function add(){
            $("count").innerHTML = count++;
            var i;
            for (i = 0; i < 100 ; i++) {
                var img = document.createElement('img');
                img.src = "dummy.png";
                $("container").appendChild(img);
            }
            if (is_run) setTimeout(reload, 100);
        }

        window.onload = function(){
            $("reload").addEventListener("click", reload, false);
            $("stop").addEventListener("click", function(){
                is_run = false;
            }, false);
            add();
        };
    </script>
</head><body>
    <div id="stop">stop</div>
    <div id="reload">reload</div>
    <div id="count">0</div>
    <div id="container"></div>
</body></html>
きっとamachangなら理由わかってそうだなー。という気はしてる。

おまけ

leaksコマンドと言う便利コマンドがあるので、実行したりウインドウ閉じたり開いたりした時の結果もはっときます。
なんか色々leakしてるけど、今回と関係あるかどうかはわからない。

実行当初
$ leaks  7011
Process 7011: 199039 nodes malloced for 19823 KB
Process 7011: 0 leaks for 0 total leaked bytes.
どんどんメモり増える
$ leaks  7011
Process 7011: 305529 nodes malloced for 30869 KB
Process 7011: 0 leaks for 0 total leaked bytes.
凄い増えた
$ leaks  7011
Process 7011: 1067031 nodes malloced for 107063 KB
Process 7011: 0 leaks for 0 total leaked bytes.
アクティビティモニタのRSIZEももりもり増える
ウインドウ閉じる
$ leaks  7011
Process 7011: 205175 nodes malloced for 20180 KB
Process 7011: 1 leak for 16 total leaked bytes.
Leak: 0x1ca2dbc0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x15015080 0x00000004 0x00000000 	..[..P..........
mallocedのサイズが減ってるけどRSIZは変わらず。そして1個リーク。
ウインドウ開いた
$ leaks  7011
Process 7011: 205273 nodes malloced for 20262 KB
Process 7011: 4 leaks for 64 total leaked bytes.
Leak: 0x16c0d300  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x02015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca2dbc0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x15015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca376a0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x01015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1cae0120  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x03015080 0x00000004 0x00000000 	..[..P..........
RSIZEかわらず。3個リーク増えた。
再度実行
$ leaks  7011
Process 7011: 269750 nodes malloced for 26522 KB
Process 7011: 4 leaks for 64 total leaked bytes.
Leak: 0x16c0d300  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x02015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca2dbc0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x15015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca376a0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x01015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1cae0120  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x03015080 0x00000004 0x00000000 	..[..P..........
またまた増えた
$ leaks  7011
Process 7011: 1354957 nodes malloced for 131749 KB
Process 7011: 4 leaks for 64 total leaked bytes.
Leak: 0x16c0d300  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x02015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca2dbc0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x15015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca376a0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x01015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1cae0120  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x03015080 0x00000004 0x00000000 	..[..P..........
もっかいウインドウ閉じた
$ leaks  7011
Process 7011: 209735 nodes malloced for 20861 KB
Process 7011: 5 leaks for 80 total leaked bytes.
Leak: 0x16c0d300  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x02015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca2dbc0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x15015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1ca376a0  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x01015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1cadd650  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x0b015080 0x00000004 0x00000000 	..[..P..........
Leak: 0x1cae0120  size=16	instance of 'TSMInputSource', type CFType, implemented in HIToolbox	
	0xa05bcee0 0x03015080 0x00000004 0x00000000 	..[..P..........
リーク増えた

Posted by Yappo at 21:04 | Comments (3) | TrackBack