プログラミングErlang 読了
プログラミングErlang を読み終えた。読んだきっかけは、rui さんによる Erlang のすすめだったと思う。
java.util.concurrent に感動して、Shibuya.lisp の宴会で、同じくJava並行処理プログラミングを読んだ ruiさんと「あれすごいよねー。という話に」。
Mosh のスレッド対応は java.util.concurrent のようなものにしたいと考えていると話したところ、「
それならば、まずその前に Erlang のプロセスモデルを勉強した方がいいよ」と教えてくださったのだ。
期待値がとても高かったのだが、それを上回って本当にすばらしい本と言語だった。一時期皆を熱くさせた理由もよく分かる。
Erlang は関数言語なのもあって、万人向けの本ではないが、自分が作るものには大きな影響を与えることは間違いない。
特にメッセージパッシングスタイルを採用しているマイクロカーネル Mona への影響はかなり大きなものとなるだろう。
Erlang で感心した点はいくつもあるが、覚えているだけでも
- プロセスが軽いため、惜しみなくプロセスを生成する点
- リンクを利用したシンプルかつ十分なエラー処理モデル
- パターンマッチによるメッセージ処理
- Cookie (WebのCookie とは別のもの)
- mailbox
- from すらデフォルトでは送信されないことに感動
- OTP ビヘイビア
- ホットコードスワップ(こんな簡単な仕組みとは!)
- 徹底したメッセージパッシングスタイル
など。宝の山。
twitter でつぶやいたが
というのが正直な印象。
最後に、本書では触れられていないいくつかの実装の核心部分に関して疑問があったので調べてみた。
プロセス
Erlang ではプロセスを大量に高速に作り、高速にメッセージのやりとりができる。
OS を作っている経験から、これが OS のプロセスにマッピングされているとはとても思えないので実装を知りたい。
Shibuya.lisp の飲み会の時に話していた予想では、User-Level の Coroutine 的な何かだろう。
良い記事を見つけた。[erlang-questions] how are erlang process lightweight?。
おおざっぱに要約すると
- green thread である(つまりOSのプロセスのコンテキストスイッチではない)
- Erlang のプロセスモデルは immutable だからただの green thread とも違う
という感じ。納得した。
yield のタイミングが知りたかったが、コードから読み取ることは難しかった。erl_process.c だけでも 220 KB もあるし。
メッセージにおける Atom
Erlang ではメッセージに Atom を頻繁に使う。Atom は Scheme でいうところのシンボルに相当する。
同一 VM ないであれば、Atom は intern されているので、パターンマッチングに使っても軽いことは理解できる。
しかし別マシンの Erlang とのやりとりで使うとオーバーヘッドにならないのだろうか。
external.c の term_to_binary を見てみた。(これが正解かは分からない)
/* * term_to_binary/1,2 and the initial distribution message * don't use the cache. */ if (!dep || (dep->cache == NULL)) { i = atom_val(atom); j = atom_tab(i)->len; *ep++ = ATOM_EXT; put_int16(j, ep); /* XXX reduce this to 8 bit in the future */ ep += 2; sys_memcpy((char *) ep, (char*)atom_tab(i)->name, (int) j); ep += j; return ep; }
ざっと見たところ zlib で compress しているくらいで、特に何もやっていないみたい。
確かにうまい方法も思いつかないし、そういうものかもしれない。