2012-05-01
Python Developers Meeting 2012.11 開催予定です
予定は未定です。
- 日時
- 2012-11-?? 、 10:00 開場 11:00 スタートの予定です。遅くても 21:00 までには解散します。
- 懇親会
- ビアバッシュやりたいです、ただ出来るかどうか不明です
- 会場
- 未定
- 住所
- 未定
- 開場時間
- 公式開場は 10:00 ~ 11:00 のみであとは #pyfes タグを付けて迎えに来て貰いましょう。
- 参加条件
- 指定した特定の OSS に対して 2012 年中に寄付をした経験がある事
参加条件詳細
注意: 寄付したからかならず参加出来るのではなく、参加条件を満たすだけです。
2012 年中に OSS へ寄付を行った経験がある事を参加条件としてみたいと思います。
寄付先はどこでも良いです
寄付について
OSS に寄付をするきっかけってあまり無いと思うので、これがきっかけになればいいなと思いました。
自分自身も Python 温泉に参加したこと以外では寄付の経験はありません。
ただ、寄付って意外に簡単にできる貢献の一つなのかなと思っています。
キャンセルについて
当日でのドタキャンでも構いません。ただ、Zusaar にてキャンセル処理だけはお願いします。
運営
基本 @voluntas の独断と偏見で色々決まっていきます。ご了承ください。
- 主催
- @voluntas / @tokoroten / @blaue_fuchs
- ハッシュタグ
- #pyfes
公式協力者達
- togetter
- @blaue_fuchs
- スチール
- @hiroki_niinuma
お手伝いとか差し入れとか募集中です
募集中
定員は 30 名の予定です。
募集は 2012.07 が終わってから
プレゼン
がっちり Python やると見せかけて ...
- @tk0miya
- @atsuoishimoto
- @shimizukawa
- @ransui (交渉予定)
- @nishio (交渉中)
- @mopemope (交渉予定)
- @flyingfoozy (交渉予定)
- @voluntas
- @itawasa (交渉予定)
- @kenji_rikitake (交渉予定)
未決定事項
2012-04-26
Sphinx で商用のウェブサイトを立てて 4 ヶ月が過ぎた
Sphinx で会社の製品サイトを作って 4 ヶ月以上過ぎました、実際に運用してみた感想などを。
前提
デザイナー @kinofumi に依頼して、Sphinx の専用テーマを作って貰いました。@kinofumi は Jinja2 も使いこなしてしまったりとデザイナー?なのか怪しいですが、とてもステキなサイトが出来ました。
商用製品サイトなので、とにかく見やすいこと、知りたい情報が見つかることが第一に作って貰いました。
リリース環境
S3 にデプロイしてパーミッションを Public にしています。URL は DNS 指定しているだけです。
それ以上は特にやっていません。
費用
アクセスが 1 日 100 人未満です。そもそも 1000 人も見に来るようになったら問題です。
で、実際いくらかかったのよ、という話しです。
今のところ三ヶ月連続で $ 0.03 で、今月も今のところ $ 0.03 でした。
円だと 2 円くらいですかね。12 ヶ月同じ調子だとして年間費用は 24 円の予定です。
デプロイ
Python の AWS ライブラリの boto で Sphinx デプロイツールを書いたのですが、
今ひとつ AWS 側のパーミッションをしっかり設定していないこともあり、今のところ手動です。
自動化したいんですけど、そこにかけるコストほどデプロイ作業がないんですよね ... あって 2 週間に 1 回くらいで、3 分かかりません ... 。
リリース
基本的に github の issues にやりたい事などをため込んで貰ってある程度たまったらリリースしています。
ただ、営業の要望は最優先でとりこんで出来るだけはやくリリースするようにしています。
拡張性
開発チームに Sphinx に明るい人がいるのはおいておいても、かなり楽です。それっぽく書けば出来ちゃいます。この辺はさすがドキュメントツールというところですね。
バージョン管理
rst 形式で管理していくので、とにかく見やすいです。HTML で管理してたら ... とおもうとぞっとします。
感想
あまりアクセスの無いサイト出あれば、すごくアリだと思いました。とにかくメンテナンスコストが低いです。Sphinx をいじるだけですし。
もっと速度が欲しければ CloudFront という手もあるでしょうけど、当面は不要そうです。
静的な製品ページやキャンペーンページにはぴったりだと思います。もし色々検討している方は導入をお勧めします。
検討している人へ
型を指定してバイナリから変換するライブラリ
作った理由
Erlang で外部 API とかを使って Console とかからデータを貰えるような仕組みを作ると、
毎回似たようなの書いててだるいなぁって思っていたので、ライブラリ化してみました。
ただ、Erlang で外部向けの API をつくったりしないかぎりは、使いどころがあまりないライブラリです。
github
pull-request 待ってます。
https://github.com/voluntas/satori
型の種類
単体では使い道無いので、 rebar の deps で呼んで貰うイメージです。
bitstring に対してバリデータ + 型変換を行って戻り値を返してくれます。
- binary
- binary extend
- integer
- atom
今のところ 4 タイプに対応しています。regexp も追加する予定です。
binary type
binary の長さのバリデーションが指定可能です。
固定で対応文字列範囲で 0x20 ~ 0x7E までの文字を許可します \00 とかはダメです。
サンプル
> satori:convert({binary, {1, 2}}, <<"ab">>). <<"ab">> > satori:convert({binary, {1, 2}}, <<"abc">>). invalid_input
binary extend type
binary と一緒ですが許可する文字範囲を自分で指定出来ます。さらに、許可しない文字も指定出来ます。
以下は 0x20 ~ 0x7E なのだけれど , は許可しないという設定をしている例です。
> satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"abc">>). <<"abc">> > satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"a,c">>). invalid_input > satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"\0\1\3">>). invalid_input
integer type
数値変換です。マイナスも大丈夫です。
最小値と最大値が指定出来てバリデーション可能です。
{integer, {最小値, 最大値}}
> satori:convert({integer, {1, 32}}, <<"12">>). 12 > satori:convert({integer, {1, 32}}, <<"33">>). invalid_input > satori:convert({integer, {1, 32}}, <<"a">>). invalid_input
atom type
ただ atom の動的生成はメモリーリークの原因になりますので、変換する際 binary_to_existing_atom を使っています。
既に存在する atom 以外を変換しようとしたら例外が上がります。それでメモリリークを防いでいます。
またリストで atom を渡す事で、指定した atom 以外は変換出来ないようにしています。
> satori:convert({atom, [spam]}, <<"spam">>). spam > satori:convert({atom, [spam]}, <<"egg">>). invalid_input
名前の由来
妖怪から取ってます。ライブラリ作るとき名前は出来るだけ日本にまつわる名前にしてます。
http://ja.wikipedia.org/wiki/%E8%A6%9A
雑感
1 時間くらいで書いたのですが、あったらいいなーと思った割にさくっと書きました。
あんまり需要は無いと思いますが、自分が嬉しいのでいいかなと。
今後は気軽に拡張出来るように拡張機能を強化していこうかなと。
ただシンプルにしていきたいので何かのアプリ依存な変換機能とかは付ける予定はありません。
参考
2012-04-21
ローカル開発時の継続ビルド+テスト Erlang 版
もちろん rebar 前提です。
OMake とか watch コマンドとか色々ありますが、自分は Python の watchdog を使っています。
watchdog は Python で出来てる監視ツールです、pip でインストールしましょう
$ pip install watchdog
.PHONY: test
compile:
@./rebar compile skip_deps=true
xref: compile
@./rebar xref skip_deps=true
clean:
@./rebar clean skip_deps=true
test: xref
@./rebar skip_deps=true eunit
watchdog はイベント系ライブラリなのですが、シェルコマンドとしても使えます。
監視は *.erl と *.hrl を src と test 以下のディレクトリを監視します。
$ watchmedo shell-command --patterns="*.erl;*.hrl" --recursive --wait --command="make test" src test
こうするとファイルを変更する度にコンパイル+テストが走ってくれるので便利です。
ただ、重いので適時 eunit suite と会わせて使いましょう。
参考
2012-04-17
string から term を生成する方法
文字列から Erlang Term を作る方法がわからなかったのでメモ。
かなりマニアックですが ... 。もっと簡単な方法があったら教えてください。
> {ok,Tokens,_} = erl_scan:string("[{foo,bar},x,3]."). {ok,[{'[',1}, {'{',1}, {atom,1,foo}, {',',1}, {atom,1,bar}, {'}',1}, {',',1}, {atom,1,x}, {',',1}, {integer,1,3}, {']',1}, {dot,1}], 1} > {ok,Term} = erl_parse:parse_term(Tokens). {ok,[{foo,bar},x,3]}
2012-04-09
Erlang/OTP R15B01 を CentOS 6.2 にインストールする
$ yum install gcc gcc-c++ ncurses-devel make openssl-devel systemtap-sdt-devel
$ curl -O http://dl.dropbox.com/u/89936/otp_src_R15B01.tar.gz
$ tar xvfz otp_src_R15B01.tar.gz
$ cd otp_src_R15B01
$ ./configure --prefix=/opt/local/erlang/R15B01 \
--enable-smp-support \
--enable-m64-build \
--enable-halfword-emulator \
--enable-kernel-poll \
--without-javac \
--disable-native-libs \
--disable-hipe \
--disable-sctp \
--enable-threads \
--with-dynamic-trace=systemtap
$ make -j8
$ sudo make install
2012-04-07
軽量ウェブサーバ Cowboy を試す
mochiweb を仕事でも使っているので特に困っていないのですが、せっかくなので cowboy を触ってみることにしました。
ちなみに、作者の @lhoguin が来月あたり日本に来るらしく、日本の Erlang な人と会いたいと行っているので興味ある人は是非。
環境と注意
Erlang: R15B01 前提です、出たばかりですが色々細かい修正がされていたりするので是非インストールしましょう。
github
https://github.com/voluntas/snowflake/tree/feature/cowboy
動かすときはこれを前提にしています。
インストール
もちろん rebar を使っていると思いますので、rebar.config に追加して終わりです。
{deps,
[
{cowboy,
".*", {git, "git://github.com/extend/cowboy.git", {branch, "master"}}},
構成
cowboy は application:start(cowboy) で起動した後、cowboy:start_listener/6 でトランスポートとプロトコル、そして acceptor を指定する仕組みになっています。
cowboy のサンプルでは app にそのまま書かれていましたが、今回は cowboy 起動部分を独立させてみました。
-module(snowflake_cowboy). -export([start/0]). -spec start() -> ok. start() -> application:start(cowboy), Dispatch = [ {'_', [ {'_', snowflake_default_handler, []} ]} ], cowboy:start_listener(snowflake_http_handler, 100, cowboy_tcp_transport, [{port, 8080}], cowboy_http_protocol, [{dispatch, Dispatch}] ), ok.
ディスパッチは {ホスト, [{パス, ハンドル名, オプション}]} のリストになっています。
今回は全部受け入れる例でにしてみました。
全てのアクセスを snowflake_default_handler に送ります。
snowflake_default_handler はただ文字列を返すだけです。
-module(snowflake_default_handler). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Any, http}, Req, []) -> {ok, Req, undefined}. handle(Req, State) -> {ok, Res} = cowboy_http_req:reply(200, [], <<"Hello cowboy!">>, Req), {ok, Res, State}. terminate(_Req, _State) -> ok.
Req は include/http.hrl にある http_req レコードです。
init でどのプロトコルを受け取るのか、state はどうするのかを指定します。
handle は Request が送られてきたときの処理を書きます。
behaviour で cowboy_http_handler を指定しておくと callback が指定されているので少しだけ便利です。
起動してみる
$ git clone git://github.com/voluntas/snowflake.git $ cd snowflake $ git checkout --track origin/feature/cowboy $ make $ sh start.sh
これで localhost:8080 にアクセスすれば起動が確認出来ると思います。
感想
まだソースを追いかけてないので良くわかっていませんが、URL Dispatch 周りがどう柔軟なのかが重要かなと感じています。
トランスポートとプロトコルを分けているので、SPDY 対応とかも出来ると言えば出来るかも知れません。
軽量かどうかの負荷試験は誰かにお任せしておきます。
まだまだ発展途上ではありますが、押さえるところは押さえているフレームワークだなと感じました。
参考
2012-03-30
LDAP クライアントが erlang/otp に追加されてた
Erlang で LDAP クライアントといえば eldap で、かなり古い実装で R8 か R9 くらいの頃の実装です。
もともとは GPL だったのが MIT になって github に公開されていました。
仕事で使うかも知れないと思って、たまにパッチを送ったりしていたのですが ...
なんと erlang/otp の maint にマージされてました ... 。
https://github.com/erlang/otp/commit/472a3d910595d7de1e49f241c1d241827b5c0bf4
テストやドキュメントもしっかりと追加されていたり。maint ブランチは次のリリース向けのブランチなので R15B01 には eldap が入るのが確定しました。やったーと思って変更履歴見てたら、自分の、名前が、あった。
https://github.com/erlang/otp/commit/472a3d910595d7de1e49f241c1d241827b5c0bf4#L2R7
Erlang R15B01 で DTrace(SystemTap) を使ってみる
注意: DTrace まったくわかりません。D 言語(D スクリプト) は書けません。読めません。
とりあえずインストールして動かしてみたよ、程度のレベルです。
DTrace 使ったらこんなに幸せになったよエントリーではありません。
追記
- 2012-04-04
- R15B01 が出たので R15B01 に合わせました。
環境
- OS
- Mac OS X 10.7.3
- CPU
- Core 2 Duo 1.6 G
- Mem
- 4G
インストール
R15B01 をビルドします。--with-dynamic-trace で dtrace を指定しましょう。
Linux の場合は systemtap を指定しましょう。--prefix の部分はお好きにどうぞ、あと hipe は自分が使う分には余り効果が無いので無効にしています。
$ curl -O http://dl.dropbox.com/u/89936/otp_src_R15B01.tar.gz
$ cd otp_src_R15B01
$ ./configure --prefix=/opt/local/erlang/R15B01 --enable-smp-support \
--enable-darwin-64bit --enable-kernel-poll --without-javac \
--disable-native-libs --disable-hipe --disable-sctp \
--enable-threads --with-dynamic-trace=dtrace
$ make
$ sudo make install
これで環境構築は終わりです。
サンプルを見てみる
注意: ファイル等は DTrace だけ表示しています。SystemTap のも同様に入っています。
サンプルは runtime_tools フォルダの examples にあります。
$ cd /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples $ ls dist.d driver1.d efile_drv.d function-calls.d garbage-collection.d memory1.d messages.d port1.d process-scheduling.d spawn-exit.d user-probe.d
efile_drv.d を見てみます ... が正直良くわかりません。勉強不足 orz
BEGIN
{
op_map[1] = "OPEN";
op_map[2] = "READ";
op_map[3] = "LSEEK";
op_map[4] = "WRITE";
op_map[5] = "FSTAT";
op_map[6] = "PWD";
op_map[7] = "READDIR";
op_map[8] = "CHDIR";
op_map[9] = "FSYNC";
op_map[10] = "MKDIR";
op_map[11] = "DELETE";
op_map[12] = "RENAME";
op_map[13] = "RMDIR";
op_map[14] = "TRUNCATE";
op_map[15] = "READ_FILE";
op_map[16] = "WRITE_INFO";
op_map[19] = "LSTAT";
op_map[20] = "READLINK";
op_map[21] = "LINK";
op_map[22] = "SYMLINK";
op_map[23] = "CLOSE";
op_map[24] = "PWRITEV";
op_map[25] = "PREADV";
op_map[26] = "SETOPT";
op_map[27] = "IPREAD";
op_map[28] = "ALTNAME";
op_map[29] = "READ_LINE";
op_map[30] = "FDATASYNC";
op_map[31] = "FADVISE";
}
erlang*:::aio_pool-add
{
printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
}
erlang*:::aio_pool-get
{
printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
}
erlang*:::efile_drv-entry
{
printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
arg0, arg1,
arg2 == NULL ? "" : "user tag ",
arg2 == NULL ? "" : copyinstr(arg2),
op_map[arg3], arg3,
arg4 == NULL ? "" : copyinstr(arg4),
arg5 == NULL ? "" : copyinstr(arg5), arg6, arg7,
/* NOTE: port name in args[10] is experimental */
(args[10] == NULL) ?
"?" : copyinstr((user_addr_t) args[10]));
}
erlang*:::efile_drv-int*
{
printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
arg0, arg1, op_map[arg2], arg2, probename);
}
/* efile_drv-return error case */
erlang*:::efile_drv-return
/arg4 == 0/
{
printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
arg0, arg1,
arg2 == NULL ? "" : "user tag ",
arg2 == NULL ? "" : copyinstr(arg2),
op_map[arg3], arg3,
arg5);
}
/* efile_drv-return success case */
erlang*:::efile_drv-return
/arg4 != 0/
{
printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
arg0, arg1,
arg2 == NULL ? "" : copyinstr(arg2),
op_map[arg3], arg3);
}
ちょっと動かしてみる
[dtrace] というのが表示されていればおkです。
$ /opt/local/erlang/maint/bin/erl Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:2:2] [async-threads:0] [kernel-poll:false] [dtrace] Eshell V5.9.1 (abort with ^G) 1>
DTrace を実行する。今回は efile_drv.d
$ sudo dtrace -qs efile_drv.d
Erlang VM 側でファイルを開いて書き込みしてみます。
Eshell V5.9.1 (abort with ^G) 1> {ok, Fd} = file:open("/tmp/spam", [raw, append, binary]). {ok,{file_descriptor,prim_file,{#Port<0.494>,14}}} 2> file:write(Fd, <<"abcdefg">>). ok
DTrace 側に以下のようなのが表示されました。
efile_drv enter tag={0,470} | PWD (6) | args: , 0 0 (port #Port<0.474>)
async I/O worker tag={0,470} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,470} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,470} | PWD (6) ok
efile_drv enter tag={0,471} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_scan.beam , 0 0 (port #Port<0.475>)
async I/O worker tag={0,471} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,471} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,471} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,472} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_scan.beam , 0 0 (port #Port<0.476>)
async I/O worker tag={0,472} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,472} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,472} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,473} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_scan.beam , 0 0 (port #Port<0.477>)
async I/O worker tag={0,473} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,473} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,473} | READ_FILE (15) ok
efile_drv enter tag={0,474} | PWD (6) | args: , 0 0 (port #Port<0.478>)
async I/O worker tag={0,474} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,474} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,474} | PWD (6) ok
efile_drv enter tag={0,475} | PWD (6) | args: , 0 0 (port #Port<0.479>)
async I/O worker tag={0,475} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,475} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,475} | PWD (6) ok
efile_drv enter tag={0,476} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_parse.beam , 0 0 (port #Port<0.480>)
async I/O worker tag={0,476} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,476} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,476} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,477} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_parse.beam , 0 0 (port #Port<0.481>)
async I/O worker tag={0,477} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,477} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,477} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,478} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_parse.beam , 0 0 (port #Port<0.482>)
async I/O worker tag={0,478} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,478} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,478} | READ_FILE (15) ok
efile_drv enter tag={0,479} | PWD (6) | args: , 0 0 (port #Port<0.483>)
async I/O worker tag={0,479} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,479} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,479} | PWD (6) ok
efile_drv enter tag={0,480} | PWD (6) | args: , 0 0 (port #Port<0.484>)
async I/O worker tag={0,480} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,480} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,480} | PWD (6) ok
efile_drv enter tag={0,481} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./otp_internal.beam , 0 0 (port #Port<0.485>)
async I/O worker tag={0,481} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,481} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,481} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,482} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/otp_internal.beam , 0 0 (port #Port<0.486>)
async I/O worker tag={0,482} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,482} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,482} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,483} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/otp_internal.beam , 0 0 (port #Port<0.487>)
async I/O worker tag={0,483} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,483} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,483} | READ_FILE (15) ok
efile_drv enter tag={0,484} | PWD (6) | args: , 0 0 (port #Port<0.488>)
async I/O worker tag={0,484} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,484} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,484} | PWD (6) ok
efile_drv enter tag={0,485} | PWD (6) | args: , 0 0 (port #Port<0.489>)
async I/O worker tag={0,485} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,485} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,485} | PWD (6) ok
efile_drv enter tag={0,486} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_internal.beam , 0 0 (port #Port<0.490>)
async I/O worker tag={0,486} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,486} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,486} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,487} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_internal.beam , 0 0 (port #Port<0.491>)
async I/O worker tag={0,487} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,487} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,487} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,488} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_internal.beam , 0 0 (port #Port<0.492>)
async I/O worker tag={0,488} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,488} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,488} | READ_FILE (15) ok
efile_drv enter tag={0,489} | PWD (6) | args: , 0 0 (port #Port<0.493>)
async I/O worker tag={0,489} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,489} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,489} | PWD (6) ok
efile_drv enter tag={0,490} | OPEN (1) | args: /tmp/spam , 6 0 (port #Port<0.494>)
async I/O worker tag={0,490} | OPEN (1) | efile_drv-int_entry
async I/O worker tag={0,490} | OPEN (1) | efile_drv-int_return
efile_drv return tag={0,490} | OPEN (1) ok
efile_drv enter tag={0,491} | PWD (6) | args: , 0 0 (port #Port<0.495>)
async I/O worker tag={0,491} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,491} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,491} | PWD (6) ok
efile_drv enter tag={0,492} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./io_lib_pretty.beam , 0 0 (port #Port<0.496>)
async I/O worker tag={0,492} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,492} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,492} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,493} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/io_lib_pretty.beam , 0 0 (port #Port<0.497>)
async I/O worker tag={0,493} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,493} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,493} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,494} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/io_lib_pretty.beam , 0 0 (port #Port<0.498>)
async I/O worker tag={0,494} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,494} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,494} | READ_FILE (15) ok
efile_drv enter tag={0,495} | PWD (6) | args: , 0 0 (port #Port<0.499>)
async I/O worker tag={0,495} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,495} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,495} | PWD (6) ok
efile_drv enter tag={0,496} | PWD (6) | args: , 0 0 (port #Port<0.500>)
async I/O worker tag={0,496} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,496} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,496} | PWD (6) ok
efile_drv enter tag={0,497} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_bits.beam , 0 0 (port #Port<0.501>)
async I/O worker tag={0,497} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,497} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,497} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,498} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_bits.beam , 0 0 (port #Port<0.502>)
async I/O worker tag={0,498} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,498} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,498} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,499} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_bits.beam , 0 0 (port #Port<0.503>)
async I/O worker tag={0,499} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,499} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,499} | READ_FILE (15) ok
efile_drv enter tag={0,500} | PWD (6) | args: , 0 0 (port #Port<0.504>)
async I/O worker tag={0,500} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,500} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,500} | PWD (6) ok
efile_drv enter tag={0,501} | PWD (6) | args: , 0 0 (port #Port<0.505>)
async I/O worker tag={0,501} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,501} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,501} | PWD (6) ok
efile_drv enter tag={0,502} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./eval_bits.beam , 0 0 (port #Port<0.506>)
async I/O worker tag={0,502} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,502} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,502} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,503} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/eval_bits.beam , 0 0 (port #Port<0.507>)
async I/O worker tag={0,503} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,503} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,503} user tag | READ_FILE (15) | errno 2
efile_drv enter tag={0,504} | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/eval_bits.beam , 0 0 (port #Port<0.508>)
async I/O worker tag={0,504} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,504} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,504} | READ_FILE (15) ok
efile_drv enter tag={0,505} | PWD (6) | args: , 0 0 (port #Port<0.509>)
async I/O worker tag={0,505} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,505} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,505} | PWD (6) ok
efile_drv enter tag={0,506} | WRITE (4) | args: , 14 6 (port #Port<0.494>)
async I/O worker tag={0,506} | WRITE (4) | efile_drv-int_entry
async I/O worker tag={0,506} | WRITE (4) | efile_drv-int_return
efile_drv return tag={0,506} | WRITE (4) ok
なんとなくわかる気にはなりますが ... 正直わかりません。
感想
DTrace は仕事で Solaris 触ってるときに使おうかなー使おうかなーとおもって結局使いませんでした。そして気付いたら仕事は Linux メインになっていたので触る機会なし。ただ Erlang VM が DTrace(SystemTap) に対応したので、ドキドキワクワクしながら使ってみました。
良くわからないけど覚えたら凄く便利そう、というのが正直な感想です。
DTrace は Oracle が SystemTap は RH が中心になって開発しているっぽいので、当面はゴリゴリ開発されるのだと思います。
Erlang の DTrace は 2008 年頃に一瞬出てきてしぼんでいたのを Basho のメンバーが復活させて最後には otp にまで突っ込むという素敵な方針に。
R15B01 が出たら標準で使えるようになる事もあり、今後は積極的に使っていこうと思います。
Erlang でアプリを書いている以上、I/O 周りとの戦いは終わることはありません。今回がいいきっかけになったと思っております。
参考
- Basho の日本大好き Scott Lystig Fritche さんによる資料
- DTrace
広告
2012-03-28
Erlang + SPDY + TLS NPN が Firefix 11 で動いた
まったりと SPDY を追っかけたりしてます、今更かよ、遅いよとか禁止。
Chrome では既に動いていましたが、Firefox も 11 から有効に出来る様になりましたね。
Jetty が対応したり、Netty が対応したり(Twitter がパッチを送ったそうですね)とちょっとワクワクしています、流行らないで終わるかも知れませんが ... 。
結果
Firefox 11 + erlang-spdy + erlang/otp 'pu' ブランチで無事動きました。
緑色の稲妻は SPDY で通信しているかどうかを確認する Firefox Add-On です。
- SPDY indicator https://addons.mozilla.org/ja/firefox/addon/spdy-indicator/
経緯とかやったこととか
Google が出してる SPDY と TLS NPN の IETF draft をざっくり読んで何となく把握。
で、やっぱり動かしたいなぁと。
ただ TLS NPN は TLS 拡張なので TLS を色々いじらないと行けないのでやっかいなんですよね。
Erlang/OTP の 'pu' ブランチに NPN の実装が入っていたりしたのでそれをビルドしたりして動かしてみました。
RJ が前に書いた erlang-spdy というデモサーバを動かしてみました。普通の SPDY はデモ用で実際は使われないと思ったので HTTPS + SPDY やりたかったんですよね。
TLS NPN も無事動いて HTTPS 上の SPDY が動作しました。これを mochiweb に統合したりしたら楽しいだろうなぁと思ったりしています。
そのうち SPDY について自分が理解したことをまとめたいと思っています。
参考資料
- TLS Next Protocol Negotiation Extension
- http://www.chromium.org/spdy/spdy-protocol
- http://tools.ietf.org/html/draft-mbelshe-httpbis-spdy-00
- http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-02
- http://technotes.googlecode.com/git/nextprotoneg.html
- https://github.com/RJ/erlang-spdy
- http://erlang.org/pipermail/erlang-questions/2011-May/058197.html
- http://erlang.org/pipermail/erlang-patches/2011-December/002539.html
- http://docs.python.org/dev/library/ssl.html#ssl.SSLSocket.selected_npn_protocol
- https://issues.apache.org/bugzilla/show_bug.cgi?id=52210
- https://groups.google.com/group/mozilla.dev.tech.network/browse_thread/thread/3907c7edb646cf41
- http://speakerdeck.com/u/chris/p/you-aint-spdy-ruby-nation
- http://builder.japan.zdnet.com/html-css/35013644/
2012-03-24
Erlang + UUID ライブラリを触ってみる
RFC 4122 で定義されている UUID を Erlang から使うにはどうやるのかなと思って調べてみました。
詳細は参考に書いた "UUID と Perl について" という記事が素晴らしいので、それを読んで下さい。
Erlang の NIF バインディングはこれ、rebar の設定が古いので後で pull-request かな。
- yrashk/erlang-ossp-uuid https://github.com/yrashk/erlang-ossp-uuid
使ってみる
なにやらバージョンが 5 つあるようです。
version 2 以外全てに対応しているようです、というか普通そうなのかな。
Version 1
> ossp_uuid:make(v1, binary). <<70,47,19,80,117,181,17,225,140,150,88,85,202,250,121,45>>
Version 3
> ossp_uuid:make(v3, binary, "ns:URL", "http://example.com"). <<214,50,181,12,121,19,49,55,174,154,45,147,245,110,112,213>>
Version 4
> ossp_uuid:make(v4, binary). <<219,96,70,1,157,163,74,19,149,208,197,55,50,210,184,125>>
Version 5
> ossp_uuid:make(v5, binary, "ns:URL", "http://example.com"). <<140,157,220,176,128,132,90,127,169,136,16,149,171,24,181,223>>
結論
負荷試験とかやってないので何ともですが、まぁ使えるかなぁって感じですね。
参考
- UUID と Perl について - daily dayflower http://d.hatena.ne.jp/dayflower/20090306/1236314881
- OSSP: OSSP uuid http://www.ossp.org/pkg/lib/uuid/
- 汎用一意識別子 - Wikipedia http://ja.wikipedia.org/wiki/%E6%B1%8E%E7%94%A8%E4%B8%80%E6%84%8F%E8%AD%98%E5%88%A5%E5%AD%90
- yrashk/erlang-ossp-uuid https://github.com/yrashk/erlang-ossp-uuid
- www.ietf.org/rfc/rfc4122.txt http://www.ietf.org/rfc/rfc4122.txt
Mac OS X に gevent をソースコードからインストールする
gevent: A coroutine-based network library for Python http://www.gevent.org/
pip からではなくソースから入れる方法を。pip でも dev を入れられたりするのかな。
追記
環境
インストール
cython と greenlet を入れます
$ pip install cython greenlet
gevent リポジトリのミラーが github にあるのでそこから入れます。
https://github.com/schmir/gevent
build して install
$ python setup.py build
$ python setup.py install
$ ipython Python 2.7.2 (default, Jun 15 2011, 16:46:46) Type "copyright", "credits" or "license" for more information. IPython 0.12 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. >>> import gevent >>> from gevent import socket >>> urls = ['www.google.com', 'www.example.com', 'www.python.org'] >>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls] >>> gevent.joinall(jobs, timeout=2) >>> [job.value for job in jobs] ['74.125.235.178', '192.0.43.10', '82.94.164.162']
これで準備出来ました。ただ公式サイトのドキュメントは 0.13 系なので、開発版とは色々違うと思うのでそこはソースを読みましょう。
参考
- Mac OS X に gevent をインストールする - Heavens hell http://d.hatena.ne.jp/heavenshell/20100707/1278476121
- python - installing Gevent on OSX - Super User http://superuser.com/questions/303962/installing-gevent-on-osx
2012-03-22
自分の興味の範囲を再確認する
追記
- 2012-04-27
- Clojure は一旦撤退
- OpenFlow は一旦撤退
- 2012-04-08
- eldap が otp に入った
- cowboy も追いかける
- flake/folsom を削除
Erlang
バインディング系は外してます。
- rebar
- 無いと死ぬ
- meck
- 無いと死ぬ
- mochiweb
- 一番使い慣れてるだけ、本当は cowboy も試したい
- jiffy
- eldap
- エンタープライズでは人気なのですよ ...
- OTP に入った!
- webmachine
- 使う機会がまったく無い .. が、ソースだけ読んでる
- lager
- こちらも使う機会が無いが ... が、ソースだけ読んでる
- poolboy
- proper
- QC 使いたいけど、これで十分
- cowboy
- mochiweb だけじゃいかんので
一番良く使う言語なので、結構あるかなと思ったら意外になかった。
もともとライブラリが充実しているってのもあるのかも。
Python
意外にない、Python 自体ほとんど書かないので実は無いのかも。
サービス
その他
色々抜けてるかも知れないけど、とりあえず書き出してみた。
結構手を広げすぎてる感があるな ...

