「負荷の高い」処理をスレッド プールに分離する必要があることを理解することが重要です [1]。
gevent スレッドで行われるすべての処理 (ネイティブ スレッドごとに 1 つの gevent HUB を持つことができます) は、ネットワーク リクエストの処理と応答の送信だけに集中する必要があります。
from gevent import spawn, run
from gevent.threadpool import ThreadPool
from time import sleep as heavy_load, time as now
class Globals:
jobs = 4
index = 0
greenlets = []
pool = ThreadPool(3) # change size of the pool appropriately
start = now()
def get_uername():
heavy_load(0.1)
Globals.index += 1
return "Alex {0}".format(Globals.index)
def do_something_else(username):
heavy_load(2.0)
print "Heavy job done for", username, now() - start
def views1():
"a request comes to views1 and it first returns the username"
username = get_uername()
## There is some heavy job separate done by do_something_else right after views1 is done
Globals.greenlets.append(
Globals.pool.spawn(do_something_else, username)
)
# return username
print "Returned requested username", username, now() - start
if __name__ == '__main__':
## simulate clients
for job_index in xrange(Globals.jobs):
Globals.greenlets.append( spawn(views1) )
## wait for all tasks to complete
# for greenlet in Globals.greenlets:
# try:
# greenlet.join()
# except AttributeError, e:
# greenlet.get()
run()
print "Test done", now() - start
これはテストの出力です:
python threadpool_test.py
Returned requested username Alex 1 0.101000070572
Returned requested username Alex 2 0.201999902725
Returned requested username Alex 3 0.302999973297
Returned requested username Alex 4 0.40299987793
Heavy job done for Alex 1 2.10100007057
Heavy job done for Alex 2 2.2009999752
Heavy job done for Alex 3 2.3029999733
Heavy job done for Alex 4 4.10299992561
Test done 4.10500001907
すべてのリクエストが最初に完了し、並列do_something_else
タスクがサイズ 3 のバッチでどのように実行されるかに注目してください。
ThreadPool が使用されていない場合、すべてのリクエストには追加の時間がかかりますが、これは gevent が提供するものdo_something_else
ではありません。asynchronous programming
その場合、出力は次のようになります。
Heavy job done for Alex 1 2.10100007057
Returned requested username Alex 1 2.10100007057
Heavy job done for Alex 2 4.2009999752
Returned requested username Alex 2 4.20199990273
Heavy job done for Alex 3 6.30200004578
Returned requested username Alex 3 6.3029999733
Heavy job done for Alex 4 8.40299987793
Returned requested username Alex 4 8.40400004387
Test done 8.40400004387
非同期で処理された場合、4 番目の要求が 0.4 秒ではなく 8.4 秒で完了したことに注意してください。
[1] http://code.google.com/p/gevent/source/browse/examples/threadpool.py