13

私は gevent をいじっていますが、コードがブロックされている理由とそれを修正する方法を理解しようとしています。

greenlet のプールがあり、それぞれがリモートのリサイクル サーバーからデータを収集するリサイクル クライアントと通信します。この演習では、thrift サーバーがデータを返すのに常に 1 秒以上かかります。グリーンレットをスポーンして join を実行すると、すべてが並行して実行されるのではなく、1 つずつ実行されます。私の理解では、コードが「ブロック」されているためにこれが発生していると理解monkey.patch_all()しています.

では、サルがすべてにパッチを当てて、それが何をしているのか理解しないのではなく、自分でコードをブロックしないようにするにはどうすればよいでしょうか?

私が理解していないことの例:

import time

from gevent.pool import Pool

def hello():
    print 'Hello %d' % time.time()
    time.sleep(1) 

def main():
    pool = Pool(5)
    for _ in xrange(5):
        pool.spawn(hello)

    pool.join()

if __name__ == '__main__':
    main()

出力

Hello 1345477112
Hello 1345477113
Hello 1345477114
Hello 1345477115
Hello 1345477116

gevent.sleep を使用できることはわかっていますが、その関数を通常の time.sleep でブロックしないようにするにはどうすればよいですか?

ありがとう

4

1 に答える 1

17

Greenlet は並行して実行されることはありません。それらはすべて同じプロセスと同じスレッドを共有するため、一度に実行されるのは最大でも 1 つです。

グリーンレットはコルーチン (協調からの「co」) であるため緑色であり、実行を調整する必要があるため、同時に実行されているとは言えません。Gevent はこの作業のほとんどを舞台裏で行い、libevent (または libev) からどの greenlet を実行する準備ができているかを認識します。プリエンプションはまったくありません。

あなたが与えた例ではtime.sleep(2)、プロセスをオペレーティングシステム内でスリープ状態にするため、gevent のスケジューラーは実行されず、別の greenlet に切り替えることができません。

したがって、あなたの質問に関して: 既存のコードにモンキー パッチを適用したくない場合は、gevent が呼び出し元の greenlet をスケジュールし、実行する別のものを選択できるように、すべてのブロッキング呼び出しを gevent の同等のものに手動で置き換える必要があります。

編集:モンキーパッチを適用せずにthriftでgeventを使用することについて:それが価値があるかどうかはわかりません。

thrift のライブラリを変更 (フォーク) したい場合は、ファイルを変更して次のように変更するだけですTSocket.py

import socket

に:

from gevent import socket

ただし、thrift ライブラリは gevent に依存するため、thrift を更新する場合はパッチを再適用する必要があります。

をサブクラス化TSocketし、メソッドopen()を gevent のソケットを使用するように変更して、前者の代わりに使用することもできますが、私にはもっと複雑に思えます。

私は実際に Gevent で Thrift を使用しており、簡単にするために全体にモンキー パッチを適用することを選択しています。

于 2012-08-20T16:00:37.370 に答える