ETS テーブルの存在有無を調べる

 Erlang の処理系である ERTS には手軽に利用可能なデータストアが複数用意されていて,ETS/DETS テーブルがその内の一つに当たるわけですが,プロセスとは異なり whereis/1 関数で存在の有無を確認することはできないわけです.というのは,例えば

-module(test).
-export([test/0]).

test() ->
    ets:new(test, [set, public, named_table]),
    ets:insert(test, {hoge, foo}),

    case get_test(test, hoge) of
        [{hoge, Value}] -> io:format("~p~n", [Value]);
        []              -> io:format("Pair Not Found~n");
        {error, undefined} -> io:format("Table Not Found~n")
    end.

というようなコードがあったとして,

get_test(TableName, Key) ->
    case whereis(TableName) of
        undefined -> {error, undefined};
        Tid       -> ets:lookup(Tid, Key)
    end.

上記の関数で何とかしようとしても,whereis/1 関数は常に undefined を返してしまいます.ではどうすれば良いのかと言うと,以下の通り,

get_test(TableName, Key) ->
    case catch ets:lookup(TableName, Key) of
        {'EXIT', {badarg, _}} -> {error, undefined};
        Any                   -> Any
    end.

直接エラーを catch して,badarg エラーの場合にテーブルが定義されていないと解釈すれば正常に動作させることができます.多少汚い感じもしますが ets:lookup/2 関数が badarg エラーを返すのはたぶんテーブルの未定義時のみだと思うので問題無いです.まあ気になって仕方がない方は,適当なガード文で引数の間違い等を弾けば良いのではないでしょうか.

大量プロセスが動作する際のプロファイリング

 関数の呼び出し回数を調べたいのだけど,eprof や fprof だとプロセス毎の呼び出し回数しか得ることができない….というような場合に使えるのが cprof.いくら大量のプロセスを生成してもモジュール毎の呼び出し回数だけを表示してくれるのでとても都合が良い.
http://ftp.sunet.se/pub/lang/erlang/doc/man/cprof.html

prof() ->
    cprof:start(),
    %%
    %% 適当な処理を実行
    %%
    cprof:pause(),
    io:format("~p~n", [cprof:analyse()]),
    cprof:stop().

whereis/1 関数を使用する上での注意

 ちょっと考えてみると当たり前のことなんだけど,whereis/1 関数は呼び出される頻度が多い割に若干遅い感じがするので,無闇に呼び出さないほうが良い.もしくは何らかの形でキャッシュしておくとか.
 自分のプログラムではかなり多用していて,これを削るだけで 1.5 倍くらい高速化された.

2009年度下期未踏ユースに採択されました

http://www.ipa.go.jp/jinzai/mitou/2009/2009_2/youth/gaiyou/kk-1.html
採択通知は一ヶ月以上も前に届いていたのだけど,外部に知らせるのは禁止されていました.開発は github に用意したレポジトリで行っているので,誰でも自由に見ることが可能です.ただ,プロジェクトの名称 (= レポジトリ名) は今のところ暫定的なものなので URL の掲載は避けておきます.
http://github.com/daiki41ti/kyeeva
追記: URL を採択案件概要のページに変更.また,github の開発リポジトリへのリンクも張った.

メッセージフロー

BitTorrent クライアントの実装メモ.頭が混乱してきたのでまとめてみた.なお,ダウンロード側はコネクション開始直後は choked 状態.

Tracker                     Client                                  Peers
Tracker  <- GET request     Client                                  Peers
Tracker      peers list ->  Client                                  Peers
Tracker                     Client                    Handshake ->  Peers
Tracker                     Client  <- <bitfield> message           Peers
Tracker                     Client            <request> message ->  Peers
Tracker                     Client         <interested> message ->  Peers
Tracker                     Client  <- <unchoke> message            Peers
Tracker                     Client  <- <piece> message              Peers

                         downloaded

Tracker                     Client     <not interested> message ->  Peers
Tracker                     Client  <- <choke> message              Peers
Tracker                     Client               <have> message ->  Peers

実際には choke/unchoke/interested/not interested メッセージは非同期的に送信されるので,ここでのタイミングは適当.
追記: メッセージフローを図に表したWebサイトを発見した.
http://alexmohr.com/bittorrent/btworking.html

2009年を振り返る

  • 1月
  • 2月
    • とくになし
  • 3月
    • P2P匿名掲示板をPythonで実装した.
      • 途中で機能追加に飽きたので,「大人数P2P匿名チャット」と呼ぶべきかもしれない.
  • 4月
    • Erlangの勉強を始める.
    • SIPropの皆さんに出会う.
    • 高校に入学.
  • 5月
  • 6月
  • 7月
    • ErlangでConsistent Hashingを実装した.
  • 8月
  • 9月
    • 体育祭など.
    • プログラミング関係はとくに無かった気がする.
  • 10月
  • 11月
    • C++でスキップリストを実装した.
    • Skip Graphの再実装.
      • 以前よりコードを綺麗に書けるようになった気がする.
    • 未踏ユース二次審査に行った.
  • 12月
    • VIOPSで招待講演をさせてもらった.
      • 色んな人の話を聞くことができて良かった.
    • Concurrent Joinを実装した.
    • Cでスレッドプールを書いた.

最近Cで書いたプログラム

このブログでは ErlangPython で書いたプログラムしか公開してないということに気づいたので,一気に晒すことにする.