LoginSignup
10
9

More than 5 years have passed since last update.

Actor modelが好きすぎて勢いだけで作ってしまったナニカ

Last updated at Posted at 2013-12-23

メリークリスマス。Elixir Advent Calendar 2013 24日目ですよ。

Elixirが大好きなみんなは、ErlangやRubyにも興味があると思うんですよね。ああ、もしかしたらScalaにも興味があるかもしれませんね。

RubyでElixir/Erlang/ScalaのようなActor modelを実現しようとしたら、Celluloidが定石かなと思いますし、最近はconcurrent-rubyというのも出てきましたが、でもCRubyのマルチスレッドは実質シングルスレッドだったりして(CRuby 2.0時点)、そのままでは計算機リソースを活かすことが難しいです。

というわけで先週日曜に半日かけて一通り作りました。

actoryとは

RubyでActor modelや並列処理を実現するためのフレームワークです。actoryはActor model like, concurrent and distributed framework for Rubyの略で、Oxford English Dictionaryによると、An agent , esp. an administrator ; a person who acts on behalf of another .とかA person who performs or takes part in any action; a doer.とかいう意味合いです。

特徴は4つ。

  • Actor modelっぽいMessage PassingができるAPIを提供します。
  • プラグインは動的ローディング対応です。Erlangからインスパイヤ。
  • 出来る限り並列化します。ジョブスケジューラはまだ単純ですが。。。
  • オーバーヘッド少なめ。通信&シリアライズ部分にMessagePack RPCを使っています。

用語集

  • Sender
    • actoryの送信側。
  • Receiver
    • actoryの受信側。
  • actor
    • Receiverとほぼイコール。
    • Receiverについて、Senderを意識しない文脈や、Actor modelを意識する文脈において、こう呼ぶ。

設計思想

Message Passing

Elixirとは全体的に異なります。
Elixirの<-演算子に相当する部分は、Senderで実行するmessageインスタンスメソッドとして実装しました。
ただ、Elixirで関数自体を渡すようにブロックをProcオブジェクトとして渡すことはできません。この処理はMessagePack RPCとの相性が悪く、結局のところ、渡される関数に相当する部分はプラグインの動的ローディングでカバーすることとし、Receiverで実行するメソッド名と処理対象のオブジェクト(テキストベース)を渡すという形にしました。
Receiverについても、Elixirにおけるreceive文とは、かなり異なります。
actoryでは、Actory::Receiver::EventHandlerのreceiveメソッドとして実装していますが、Elixirのreceive文におけるcase文のような振る舞い、すなわちactoryにおいて渡されたデータを見てどのプラグインのメソッドを実行するかは、Rubyの方に任せています。
処理が終わって値を返したらまた待受状態に戻るという点では、Scalaに近いかもしれません。

プラグイン

専用のディレクトリに突っ込んでおけば自動的にロードされるようにしています。
作り方としては、Actory::Receiver::Pluginとしてメソッドを定義すればオーケー。Rubyのクラスは再オープンできるので便利です。
また、Receiver自体の機能も、できるだけプラグインで実現するようにしています。

並列処理

Parallelを使っています。クライアントがSenderに渡した処理対象のデータ(配列)をバラして、それぞれをactorに振り分けています。
SenderもReceiverも、基本的にCPUコア数の分だけプロセスを生成します。これらのプロセスをどのCPUコアが処理するかはOSのジョブスケジューラ任せにしています。

通信

プロセス間通信は、MessagePack RPCを使用しています。シリアライズの高速性と扱いやすさが決め手です。

インストールとか使い方とかアーキテクチャとかプラグインの書き方とか

こちらをご覧下さい。
https://github.com/keithseahus/actory

課題

  • テストを書く
    • 半日+αくらいで、勢いだけで作ったので…。仕事ではちゃんとテスト書いてますよ(迫真)
  • 戻り値の形式改善
    • もう少し扱いやすい形式があるように思える。
  • ジョブスケジューラの追加(1)
    • actorに127.0.0.1のホストがいる場合、リモートのReceiverに投げずに、ローカルで処理した方が早い処理もある。そのためのスケジューラの追加。
  • ジョブスケジューラの追加(2)
    • actorの計算機リソースの状況を取得するプラグインは既に作ってあるので、それを使ったロードバランシングができるスケジューラが欲しいところ。ScalaのAkkaルータ的なものを実現したい。
  • メッセージング方法の柔軟性向上
    • ネットワークで例えるとユニキャスト,マルチキャスト,ブロードキャスト的な制御を任意に切り替えられるようにしたい。
  • メールボックス
    • Receiverに対するキューイング処理が欲しい。
    • Senderについても、Receiverからの返却を非同期で受け取って取り出せる機構が欲しい。
  • ゼロ・コンフィギュレーション
    • 設定ファイルでactorを列挙してしまっている時点でイケてない。

まとめ

  • Actor modelが好きすぎて勢いだけでactoryというものを作りました。
  • CRuby縛りの開発でActor modelと並列処理が欲しい時に、意外と使えるかも?
  • 明日は最終日、 @mururu さんによる完走です。
10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9