Erlangを学んでみてる

Herokuがログ収集ツールの実装に使い始めたり(参考: Logging on Heroku)、RiakやCouchDBの実装に使われてたりというので興味を持って、プログラミングErlangを読んで見てる。2008年くらいの本。

まだ半分くらいまでしか読んでないけど、アクターモデルの話とかはひと通り終わって、これから複数のノードでErlang上のプロセス連携させる話題に入る。処理系を起動させるだけで計算ノードになっていたりして、分散プログラミングに対するおもてなし度が高い。

並行プログラミングについて教えてくれる8章に練習問題がついていて、解けたらインターネットに公開しよう!って書いてあったので問題の引用と共に公開してみる。

リングのベンチマークを書いてみよう。N個のプロセスからなるリングを作り、1つのメッセージがリングをM回るようにして、
合計でN*Mのメッセージが送信されるようにする。さまざまなNとMの値について所要時間を計ってみよう。
自分が得意な他のプログラミング言語で同様のプログラムを書いて結果を比べてみよう。ブログを書いて結果をインターネットに公開しよう!

問題の意図としては、UNIXプロセスなどと比較して、Erlangのプロセスのプロセス間通信のコストが十分に小さいことが体験してほしい、ということだと思う。同時に動作するプロセスは1つだけなので並行処理というわけではない。

できたので、いろいろなN,Mについて、メッセージパッシングにかかった時間の平均/トータル時間を計測してみた。

N(1000) x M(1000) : time per message passing = 0.63 (0.616) microseconds, total = 630 (616) milliseconds
N(1000000) x M(1) : time per message passing = 0.97 (0.893) microseconds, total = 970 (893) milliseconds 
N(1) x M(1000000) : time per message passing = 0.24 (0.241) microseconds, total = 240 (241) millisecond 
N(10000) x M(10000) : time per message passing = 0.7885 (0.79047) microseconds, total = 78850 (79047) milliseconds

計測結果の秒数の括弧の外はプロセスが処理に使った計算時間、括弧内は実際にかかった時間を表す(プロセスは平行に動作するので括弧の外のほうが数値が大きい)。メッセージパッシング/トータルで単位が違う。

1000ノードに対して、メッセージを1000周させるくらいのことをしても、一度のメッセージパッシングに0.6micro sec.くらいしかかかっておらずとてもはやい。同じメッセージパッシングの量(N*Mが同値)でも、メッセージを、1000000ノードに対して1周させるのと、1ノードに対して1000000周させるのでは、1ノードを1000000周させるほうがはやい。10000ノードを10000周させるとさすがにトータルの時間はかかるようになる。

へー、という感じだけど、同じプロセスでもUNIXプロセスとは性質が違う軽量なものだということが体験できた。

他の言語と比較してみたいけど、プロセスをリング上につないでメッセージパッシングをするようなことができる言語は限られているように思う(ScalaとかGoとかあたりはできそう)。 2008年からある課題なので "ring benchmark erlang" とかで検索すると他のひとの実装も見れて面白い。

プログラミングErlang

プログラミングErlang