20

結果として、これら 2 つのライブラリは同様の哲学と同様の設計上の決定を共有しています。しかし、この人気のある WSGI ベンチマークによるeventletと、gevent. 彼らのパフォーマンスが大きく異なる理由は何ですか?

私が知っているように、それらの主な違いは次のとおりです。

  • geventは、独立したリアクター インターフェイスを定義しlibev、その背後にある、、および Twisted リアクターを使用して特定のアダプターを実装します。リアクター インターフェースを追加すると、重大なパフォーマンス ヒットが発生しますか?libeventeventletselectepoll

  • geventほとんどが Cython で書かれていeventletますが、純粋な Python で書かれています。ネイティブにコンパイルされた Cython は、計算量はそれほど多くないが IO バウンドのプログラムの場合、純粋な Python よりも高速ですか?

  • のプリミティブはgevent標準ライブラリのインターフェイスをエミュレートeventletしますが、 のプリミティブは標準とは異なり、それをエミュレートする追加のレイヤーを提供します。エミュレーション層を追加するeventletと遅くなりますか?

  • の実装はeventlet.wsgiよりも悪いですgevent.pywsgiか?

全体的にとても似ているので、本当に不思議です。

4

2 に答える 2

13

gevent は Cython で「ほとんど」書かれているわけではありませんが、いくつかの重要なセクションは Cython で書かれています。

Cython は大きな違いをもたらします。プロセッサの最適化は、コンパイルされたコードでより効果的に機能します。たとえば、分岐予測は、VM 実行レベルでの分岐の間接性が不透明であるため、VM ベースのシステムではうまくいきません。キャッシュのフットプリントはよりタイトです。コンパイルされたコードはここで大きな違いを生み、IO はレイテンシーに非常に敏感になる可能性があります。

同様に、libev は非常に高速です。同じ理由。

eventlet が select ハブを使用するべきではなかったようです (Python 2.6 は通常デフォルトで epoll になります)。ただし、select でスタックしていると、非常に遅くなります (Python は select fd_set を Python リストに前後に変換する必要があるため、ループの途中では見苦しくなります)。

私はプロファイリングを行っていませんが、libev / libevent と Cython が大きな違いをもたらすことは間違いありません。特に、スレッドプリミティブの一部は Cython in gevent にあります。多くのコードが IO や標準ライブラリを介して間接的に触れているため、これは大きな問題です。

eventlet の追加のエミュレーション レイヤーに関しては、より多くの弾みがあるように見えます。gevent では、コード パスがコールバックを構築し、ハブがそれらを呼び出せるように見えます。eventlet は、ハブが gevent で行っているより多くの簿記を行っているようです。繰り返しますが、私はそれをプロファイリングしていません。モンキーパッチ自体はかなり似ています。

WSGI サーバーは、もう 1 つの難しいサーバーです。特に、gevent でのヘッダー解析は標準ライブラリに延期されますが、eventlet では独自に実装されます。これが大きな影響かどうかは定かではありませんが、そこに何かが潜んでいたとしても不思議ではありません。最もわかりやすいのは、eventlet のサーバーが、標準ライブラリ BaseHTTPServer のモンキー パッチ バージョンに基づいていることです。これが非常に最適であるとは想像できません。Gevent は、エミュレーションを認識するサーバーを実装します。

于 2012-10-04T01:25:26.830 に答える
1

返事が遅れて申し訳ありません。

そのベンチマークで大きなパフォーマンスの違いが生じる主な理由は 2 つあります。

  • 前述のように、gevent のクリティカル パスは大幅に最適化されています。
  • そのベンチマークはストレス テストを行います。できるだけ多くのリクエストをマシンに実行させようとするため、もはや IO バウンドではありません。そこで Cythonized コードが活躍します。

「スラッシュドット」トラフィックのバースト中にのみ発生する「現実世界」。これは重要であり、準備ができている必要がありますが、それが発生した場合は、サーバーを追加するか、リソースを大量に消費する機能を無効にすることで対応します. 負荷が増加したときに実際にサーバーを追加するベンチマークは見たことがありません。

一方、ベンチマークが「通常の日」の負荷 (ウェブサイトごとに異なる) をシミュレートする場合、一般的にはリクエスト、ランダムな一時停止、繰り返しに近似できます。一時停止が少ないほど、シミュレートするトラフィックが多くなります。また、ベンチマークのクライアント側でレイテンシをシミュレートする必要があります。Linux では、これは素晴らしい netem[1] を使用して行うことができますが、それ以外の場合は、recv/send 呼び出しの前に小さな遅延を置くことによって実行できます (ベンチマークは通常、より高いレベルのライブラリを使用するため、これは非常に困難です)。

これらの条件が満たされている場合、IO バウンドの問題を実際にベンチマークします。しかし、結果はそれほど素晴らしいものではありません。すべての候補が 10、50、さらには 200 qps の負荷を正常に処理しました。退屈ですよね?そのため、レイテンシの分布、99% のリクエストを処理するまでの時間などを測定できました。Gevent の方がより良い結果を示します。しかし、その違いはほとんど印象的ではありません。

[1] Linux で遅延およびドロップされたパケットをシミュレートする

于 2013-01-24T10:05:02.180 に答える