ページ

2010年4月23日

[翻訳] geventのeventletとの比較

最近、ブログを書いていなかったので「Comparing gevent and eventlet」を訳してみました。ざっと訳しただけなので、間違っていたらごめんなさい。他のドキュメントは気が向いたら訳すかも知れませんが、多分訳さないでしょう。



この記事では、geventを始めた理由とeventletとの比較を説明します。

経緯

Bob Ippolitoは2006年にEventletの最初のバージョンを書きましたが、割とすぐに開発をやめてしまいました。Donovan Prestonは当時働いていたLinden Labの他の人とメンテナンスを行いました。ステートマシンやコールバックを使うよりも簡単にネットワークソフトウェアを方法を探しており、2008年にEventletに興味を持つようになりました。GreenletをベースとしたEventletは、当時あった他のフレームワーク(PYthonネイティブのジェネレータ、生のgreenletCorotwine)よりも、使いやすさという点で進んだものでした。

その時関わっていたプロジェクトはTwistedを使っていたので、二つのライブラリを統合することから始めました。作業をしているとEventletの大量のバグを見つけて、ほとんどのコア部分を書き換えました。修正したブランチは取り入れられて、2009年にEventlet 0.8.1としてリリースされました。その時までにDonovanはLinden Labを去っており、Ryan Williamsが主要なメンテナになっていました。

2009年の夏にネットワークライブラリを主要なコンポーネントにする新しいプロジェクトを始めました。しかし、Eventletは次の二つの要求を満たしませんでした。

  • libeventを使っているCで書かれた別のライブラリがあり、それらを統合して一つのプロセスで動作させたいので、libeventのイベントループを使う必要があった。当時のEventletはまともにlibeventをサポートしていなかった。
  • モンキーパッチでPythonのライブラリを使う予定だったので、socketモジュールが完璧に動作する必要があった。当時のEventletはいくつかのバグがあり、socketの処理が止まってしまった。

pyeventベースのhubで時間を費やしました。その結果、hub APIをピュアPythonのイベントループに対応させようとして、他のEventletのAPIと互換性がなくなりました。円滑に動作させるためには、他のすべてのhubのインターフェースと実装に大幅な変更が必要でした。socketモジュールのバグはイベントループ固有のもので、pyevent用にバグを修正しても、他のhubにはまだバグが存在していました。Eventletを大幅に書き換えるために、後継プロジェクトを開始しました。

geventはeventletのバグ修正版として開始して、いくつかの機能をドロップしました。

違い


1. geventはlibeventがベース

libeventは人気があり、ポータブルなイベントループです。Linuxではepoll、FreeBSDではkqueueのように使用するシステムの最速の仕組みでアプリケーションが動きます。ピュアPythonでのイベントループを持ち、つい最近までepollをサポートできなかったeventletと違って、geventのすべてのイベントループは実世界で、ハイスケーラブルな環境で十分テストされています。

優れたパフォーマンスは、libeventと密接に統合したメリットの一つですが、他にもメリットがあります。

  • シグナル操作はイベントループに統合されている
  • 他のlibeventベースのライブラリは、単一のイベントループでアプリケーションに統合できる
  • DNSへの要求は、ブロッキングコールで使うスレッドプールを介さずに非同期で解決される。
  • WSGIサーバはlibeventの組み込みHTTPサーバをベースにしていて、超高速

2. geventのインターフェースは標準ライブラリのインターフェースにあわせてある

たとえば、gevent.even.tEventthreading.Eventmultiprocessing.Eventと同じインターフェース、同じセマンティックですが、greenletを通して動作します。eventletはEventクラスもありますが、理由もなく独自の仕様になっています。

新しいインターフェースに明確な利点がない限り、geventでは標準的なインターフェースを使っています。いくつかのケースでは、クラス全体を歳実装する必要がなかったところでも、メソッドの仕様を標準ライブラリにあわせるように変更しました。

次のものが、仕様を変更した例です。

  • wait()は例外を発生しない
  • get()は例外を発生させるか、値を返す
  • join()はwait()のようですが、実行用です。

一貫したインターフェースはコードを読んだり理解するときのスピードをあげることができます。同様に、APIの学習を容易にします。

後方互換性を気にしなくても良いので、geventはすべてのAPIのEventletが持っていた癖を修正しました。APIの品質はユーザとeventletのメンテナが理解しています。geventのlibevent固有ではない部分は、eventletに取り入れられています

3. geventはeventletではない

geventにはeventletにあるすべての機能はサポートしていません。すでにeventletを使っている場合、次のケースではgeventに乗り換えるべきではありません。

  • eventlet.db_poolを使っている場合。geventには対応するモジュールがありません。
  • eventlet.processesを使っている場合。ライブラリにはサブプロセスのサポートがまだありません。これは、自分でサブプロセスを実装するです。
  • eventletのthreadpoolを使っている場合。geventは現在は対応するモジュールがあります。ユーザがコントリビュートしたものですが、すぐにはライブラリに組み込めないでしょう。
  • eventletをTwsitedのreactorで実行している場合。
  • libeventを使えない場合。

geventは誰でも使える小さくて安定したコアを目指しています。可能なときはいつでも、ジョブをlibeventにデリゲートします。コルーチンベースのプログラミング用に便利な抽象レイヤーを提供します。eventletにインスパイアされましたが、eventletのフォークではなく新しいAPIが特徴です。実装はもっとシンプルで、もっと安定しています。


他の人がなぜgeventを選択したかや、eventletからgeventに移行するときに発生するかも知れないことも読んでみてください。

Thanks to Marcus Cavanaugh, Brad Clements, Nicholas Piël, Andrey Popp and Bob Van Zant for reading drafts of this.

0 件のコメント: