3

このスクリプトのパフォーマンスはどうですか: http://tornadogists.org/2185380/以下にコピーします。

from time import sleep
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, asynchronous, RequestHandler
from multiprocessing.pool import ThreadPool

_workers = ThreadPool(10)

def run_background(func, callback, args=(), kwds={}):
    def _callback(result):
        IOLoop.instance().add_callback(lambda: callback(result))
    _workers.apply_async(func, args, kwds, _callback)

# blocking task like querying to MySQL
def blocking_task(n):
    sleep(n)
    return n

class Handler(RequestHandler):
    @asynchronous
    def get(self):
        run_background(blocking_task, self.on_complete, (10,))

    def on_complete(self, res):
        self.write("Test {0}<br/>".format(res))
        self.finish()

HTTPServer(Application([("/", Handler)],debug=True)).listen(8888)
IOLoop.instance().start()
  1. 私のアプリケーションは1,000 req/secをはるかに超えます。
  2. 各リクエストは 2 ~ 30 秒続き、平均で約 6 秒かかります
    • 単純平均sleep(6)
  3. redis BLPOPまたはのようなものを使用して IO をブロックします。Queue.get_nowait()
4

1 に答える 1

2

全体的なパターンは問題ありませんが、GIL のおかげで、スレッド プールは 1 つの CPU しか使用できず、利用可能なハードウェアを最大限に活用するには複数のプロセスを使用する必要があることに注意してください。

数値を詳しく見てみると、リクエストが実際にそれぞれ平均 6 秒かかる場合、10 スレッドは小さすぎます。毎秒 6000 秒相当の作業が行われるため、すべてのプロセスで少なくとも合計 6000 のスレッドが必要です (6 秒が実際には外部イベントと Python プロセスの CPU コストをブロックしているだけであると想定しています)。無視できる)。最新のシステムで処理できるスレッドの数はわかりませんが、6000 の Python スレッドは素晴らしいアイデアとは思えません。リクエストごとに 6 秒のブロック (および 1 秒あたり数千のリクエスト) が実際にある場合は、これらのブロック関数を非同期に変換する価値があるように思えます。

于 2013-09-26T04:16:19.567 に答える