2008年07月24日
Erlang/OTP
こんにちは。先日、「困ります、ファインマンさん」を読んでいて、ファインマン博士が晩年Thinking Machines社と関わりがあったことを知りました。Thinking MachinesはかつてLEDの赤い光が蠢くスーパーコンピュータを作っていた会社です。製品のコネクションマシンシリーズはハードウェアは優れていたものの、良い処理系が揃わず商品としては失敗したそうですが、超並列計算機の可能性を示すものとなりました。さて、そのコネクションマシン(CM-2)が登場した1987年ごろにスウェーデンでひとつのプログラミング言語が生まれます。電話交換機での並行処理を目的としたもので、Erlangと名づけられました。今回はこのErlangの話です。
ちょっと強引でしたが、ここ数週間Erlangをさわっていて並列/並行計算に親しみがわいたので、こんな前振りにしてみました。Erlangは2007 年あたりから2度ほどブーム(?)になったようなので、知っている方もいらっしゃるかと思いますが、私のようにスルーしていた方へErlangの紹介を引用しておきます。
Erlang は概ね関数型であり、動的型付けされる言語であり、並行プログラミングだとか分散型プログラミングという考え方に重心が置かれたものです。Erlangプ ログラムは小さなプロセスの集まりであり、個々のプロセスはそれぞれ固有の状態と他のプロセスとの非同期メッセージのやり取りによって情報のやり取りをします。(中略)Erlangが提唱することの一つは、伝統的なスレッドモデルに縛られていないもう一つの並行モデルです(プログラムを正しく動作させるこ とがとても難しいので、わたしはスレッドモデルを嫌っています)。それに加えて、並列するプログラムをコンピュータ一台にのみ置くのではなく、コンピュータのクラスタ全体にばら撒くということをほとんど余計な作業をすることなく行います。 ― ときどきの雑記帖 基礎となるプログラミング言語
※文中のプロセスはメモリを共有しない並行の実行単位という点では類似していますが、OSプロセスのことではありません。
なぜErlang?
このブログはMMOゲームの開発を中心に話題を選んでいますが、Erlangの(というよりOTPのですが)可用性を高めるための仕組みや、言語と一体となったRPC、自在に配置可能な軽量プロセスなどが、MMOゲームサーバ・クラスタの構築を相当容易にしてくれるかもしれない、と考えたからです。1万人以上をひとつのゲームサーバに詰め込むことはなかなか難しいようですから、早晩クラスタ化せざるを得ません。これがウェブ開発であれば、データベース以外は何も共有しない方法でスケールすることがはっきりしています。ウェブサーバとレプリケーションしたMySQLとmemcachedという組み合わせです。もちろん、ゲーム開発でもこうした考えやツールは有用ですが、長時間に渡る多数の接続、高頻度で小さいリクエスト、サーバプッシュ、世界のシミュレーションなどがあり、全く同じにはできません。過去取り上げたOOOのライブラリもクラスタリングという点ではサポートがありません。そういう訳でちょっとErlangを見てみることにしました。
プログラミングErlang
まず、バイブル的なプログラミングErlangを読みました。最初、関数型の壁があると思っていたのですがそんなことはなく、一回しか代入できない変数、リスト操作、ちょっと変わった書き方のループ(末尾再帰)に慣れればほとんど手続き型のようでした。関数型ということを控えめにして、逐次プログラミングから入る本の構成が良いです。なんだか肩透かしを食ったようでしたが。7章あたりから俄然面白くなってくるので、これから読まれる方はそこまでは耐えましょう。ホットコードスワッピング対応サーバのくだりではなんてシンプル!と驚かれると思います。思いがけず良い書籍だったのでなんだか得した気分でした。
※ホットコードスワッピング:稼働中の動的コードアップグレード
OpenPoker
次にそこそこ量のあるコード、できればゲームサーバのものを読みたいなと思い探してみるとポーカーサーバのコードを見つけました。「Writing Low-Pain Massively Scalable Multiplayer Servers」という題でDevMaster.netに記事もあります。1万行ありますがErlang/OTPだけで完結しているため勉強にはちょうどいい規模でした。ノートを取りながら読み進めて、こんな全体像(下)が見えました。
ルー ルにカジノで遊べるテキサス・ホールデムなどがあり、そうしたところは少し複雑ですがその他は直線的な作りと思います。ゲームノードはあとで追加が可能で すが、残念なことにホットコードスワッピングやスーパーバイザなどは利用していないため、そうしたことは参考になりません。パケットの扱いやErlangの内部データ構造との変換、Mnesia(Erlang付属のDB)の扱い、ゲームの世界のモデル化など、Erlangでゲームを作るやり方が分かるのは 良いですね。
※スーパーバイザ:プロセスのクラッシュを検出して再起動する監視プロセス
感想
そして、こんな感想を持ちました。
- 動的コードアップグレード、監視ツリーにモニタ、SNMPサポート、DB含め、耐障害性を高めるための仕組みが整っている。エラーと共に生きると形容すればよいのか……
- OTPの作りを見ると実用本位ということがよく伝わってくる。ちゃんと動く。インタフェースは古めかしいけれど、カバレッジアナライザ、プロファイラ、デバッガ、アプリケーションモニタ、ツールも一通りはある。
- ローカルもリモートもメッセージ通信は透過的。もちろん抽象化の破れはあって、ローカルとLANでは速度差が大きいので意識しておくことは必要だけれど、それでもうれしい。
- 少しでも逐次的でないところがあれば、すぐにプロセスとメッセージ通信を使うことになる。宣言的ではなくなる。日常的に並行思考。ゲームデベロッパはプロセスをタスク/アクター/エンティティに置き換えれば考えやすいかも。
- いくらプロセスが並列で動くといっても、元々のVM/コンパイラの性能がそれほどでもないので、思ったほどパフォーマンスが出ないことがある。それをマシン数で補おうとすると、通信がボトルネックになって……結局は1ノードが許容できる性能かということ。CとJavaの言語バインディングがあるので、改善はできるかもしれない。例:FacebookチャットのログはC経由
- 意外にMnesiaが快適。当たり前のようにレプリケーションして使える。是非は別にして分散トランザクションもある。ストレージ不足(2Gの上限がある)は気がかりだけれど、工夫できなくもなさそう。フラグメント化したり、MySQL&memcachedと組み合わせたり、ゆくゆくはKaiやTokyo Cabinetが使えるかもしれない。
ゲームデベロッパはどうか分かりませんが、本格的に使うウェブデベロッパは少しずつ増えているようで、これからより多くの情報が出てくることでしょう。Facebookチャット開発者が言った「問題のドメインがグローブのようにErlangとぴったり合う」というのをMMOゲームでも感じたので、しばらく追いかけてみるつもりです。
ちょっと取り留めのない感じになってしまいましたが、これでおしまい。


Leave a Comment
Trackbacked