Clojure記事紹介<百日修行>(4):「PulsarでActorプログラミング」
Clojure記事紹介<百日修行>では、英文で書かれたClojureの記事を要約してひたすら紹介していきます。モットーは「質より量」です。
紹介記事
レベル:中級
Pulsarを用いた、Actorモデルを使った並行プログラミングの紹介記事です。
取り上げられているライブラリ:
Actorモデルで並行プログラミング
Pulsarは、JavaのQuasarというライブラリのClojureバインディングで、Actorモデルを実現するライブラリです。
Actorモデルは、並行処理を記述するためのプログラミングモデルの1つで、Actorと呼ばれる互いに独立した(データを共有しない)プロセスがメッセージをやりとりすることによって処理を進めていきます。Erlang/Elixirといった言語や、Scala/JavaのAkkaなどが有名でしょう。
Actorモデルの利点は、 * 各Actorは共有データを持たないため、データの競合が起きない(起きにくい) * Erlang/Elixirでは、各Actorがメモリ管理などの面で独立しているため、エラー・障害に強い * 計量スレッドやグリーンスレッドで実装されることによって、通信・ディスクアクセスなどのIOを大量に行う際の並列性が確保でき、またレイテンシが隠蔽できるためスループットが向上する
といった物があります。逆にデメリットとしては、
- 規模が大きくなると、多数のActorを管理するのはプログラミング上難しい
- どれくらいのActorが並行動作できるかどうかは実装次第
- 計量スレッドをサポートしていないプラットフォームでは実装がトリッキーになりがちで、制限が多いこともある(JVMとか)
あるかと思います。(私はプログラミング言語の専門ではないので詳しくないです)
Pulsarでプログラミング
この記事では、サンプルとして、非常に簡易なチャットシステムのようなものを作製しています。サーバーの方だけソースコードを転載するので、リンク先でクライアント側のソースも是非参照してください。
各Actorは、受信したメッセージによって場合分けをする、イベントループのような構造の関数を定義します。ソースコード中のreceive
と呼ばれる式がそうです。
(defn- get-name [ref clients] (-> (first (filter #(= (:ref %) ref) clients)) :name)) (defn- broadcast [msg clients] (doseq [c clients] (! (:ref c) msg))) (defsfn server [clients] (receive [:join ref name] (do (link! ref) (broadcast [:info (str name " joined the chat")] clients) (recur (conj clients {:name name :ref ref}))) [:send ref msg] (do (broadcast [:new-msg (get-name ref clients) msg] clients) (recur clients)) [:exit _ ref _] (let [updated-clients (remove #(= (:ref %) ref) clients)] (broadcast [:info (str (get-name ref clients) " left the chat")] updated-clients) (recur updated-clients)) :shutdown (println "Shutting down"))) (defn create-server [] (spawn :trap true server '()))
個人的な感想としては、ちょっと記法にクセがあるのが気になるのと、これならcore.asyncでよくね?という気がします。
Clojure Applied: From Practice to Practitioner
- 作者: Ben Vandgrift,Alex Miller
- 出版社/メーカー: Pragmatic Bookshelf
- 発売日: 2015/09/06
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: Stuart Halloway and Aaron Bedra,川合史朗
- 出版社/メーカー: オーム社
- 発売日: 2013/04/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (10件) を見る