本連載では第一線のPerlハッカーが回替わりで執筆していきます。第2回は、Japan Perl Association代表理事の牧大輔さんで、テーマはAnyEventです。
はじめに
昨今のPerl界で最も熱い話題がイベント駆動プログラミングです。イベント駆動プログラミングはいわゆる「リアルタイムWeb」などと呼ばれる、大量のデータや接続をさばきつつも更新通知の速さが重要となるアプリケーションでは必須技術で、今後のエンジニアにとって最も重要な知識の一つと言えるでしょう。
イベント駆動プログラミング自体はPerlでも以前からさまざまな用途に使われてきましたが、それがまた見直されているのは、従来のイベント駆動プログラミング用ツールキットの使いやすさをはるかに凌駕するAnyEventというモジュールが成熟期を迎えたためです。
イベント駆動プログラミングとは
AnyEventの解説に入る前に、簡単にイベント駆動プログラミングの概念をおさらいしましょう。
普通のプログラミングではプログラム全体の処理命令を記述し、それらをすべて処理し終わればプログラムが終了します。たとえば図1のようなコードでは、処理1より前に処理2が実行されることは絶対にありません。
このように実行されるコードとその順番が明示的に書かれている普通のコードとは違い、イベント駆動プログラミングでは各処理の実行のタイミングは基本的に「イベントループ」が担当します。プログラマはこのイベントループにコールバックを預けておき、ある条件が満たされたときにイベントループがそのコールバックを実行するように実装します(図2)。
これだけでは単純に書き方が違うだけに見えるかもしれませんが、イベント駆動プログラミングの最大の魅力は、処理をこのように分離することで協力式マルチタスキング(Cooperative Multitasking)に似た疑似並列処理を1プロセス内で行えることです。
たとえば従来の書き方ではネットワークからの入力待ちで処理を停止しなければいけないところをイベントループに「入力が読み取れる状態になったらこのコールバックを呼んでください」と登録しておき、次の処理を進めます。どこかの段階でイベントループがその状態を感知すると登録されていたコールバックを呼び出してくれるので、その入力値を使って作業を進めるというようなことができます。
このように本来待ち時間としてロスが生じてしまう部分でほかの処理を進めるように協力し合うことで、同一プロセス内で複数の処理を並行して実行できるようになり、「協力式」なマルチタスキングが実現できるわけです。また、1プロセスで並列処理を行えるので、うまく処理を組めればマルチスレッドやマルチプロセスを使ったマルチタスキングよりはるかに少ないリソースで並列性を確保できます。
なお、「イベント駆動プログラミング」はこのようにI/Oを非同期処理し「あとで処理できるときにする」用途に使うため、「非同期プログラミング」(Asynchronous Programming)と同じ意味で呼ばれることがよくあります。本稿ではイベント駆動を使った結果の非同期通信を使う場合は「非同期」と表記しています。
AnyEventとは
AnyEventは2004年に最初のバージョンが発表されたライブラリです。当初は、POE、IO::Async、Event、EVなどのイベントループの差異を吸収し、実装に依存しない形でイベント駆動プログラムを書けるようにするために開発されました。
しかし現在ではAnyEventは他ライブラリのラッパーとしてではなく、スタンドアローンのイベント駆動ツールキットとして完成していると言えます。ラッパーとして最小公約数的なAPIを追求した結果、ほかのイベント駆動ライブラリをまったく使わずAnyEventのAPIを使うだけで、複雑なイベント駆動プログラムも実装できるようになったのです。イベント駆動のライブラリやアプリケーションを書くのであれば、現在ではAnyEventだけで十分な場合がほとんどです。
AnyEventのインストール
AnyEventをインストールするにはCPANからダウンロードするか、cpanツールを実行してインストールしてください。
もしCコンパイラが使える環境で今後積極的にAnyEventを使うのであれば、同じ作者が開発しているEVもインストールしておくとよいでしょう。EVはAnyEventのバックエンドの実装の中では現時点では最も高速に動作します(インストールしておけば、明示的に指定しなくてもAnyEventがEVを使用するようになります)。