Утилизация торнадо медленнее, чем темы - PullRequest
0 голосов
/ 12 мая 2018

Я реализовал простую утилизацию веб-страниц с использованием торнадо, основная идея - вставить все URL-адреса в очередь q и вызвать нескольких рабочих, проверить связь с URL-адресом и проверить его состояние (большинство URL-адресов не существует, т.е. получение тайм-аутов)

все ответы вставлены в другую очередь q2, но это не имеет значения, поскольку обработка этой очереди происходит после того, как все рабочие сделали

Я также применил ту же методологию, используя потоки с тем же номером, что и concurrency и реализация потоков намного быстрее, хотя шаги простаивают во время ожидания ответа от сети, в то время как торнадо IOLoop должен быть оптимальным для такого поведения

что мне не хватает?Thx в продвинутом

from tornado import httpclient, gen, ioloop, queues

concurrency = 100

@gen.coroutine
def get_response(url):
    response = yield httpclient.AsyncHTTPClient().fetch(url, raise_error=False)
    return response


@gen.coroutine
def main():
    q = queues.Queue()
    q2 = queues.Queue()

    @gen.coroutine
    def fetch_url():
        url = yield q.get()
        try:
            response = yield get_response(url)
            q2.put((url, response.code))
        finally:
            q.task_done()

    @gen.coroutine
    def worker():
        while True:
            yield fetch_url()

    for url in urls:
        q.put(url)

    print("all tasks were sent...")

    # Start workers, then wait for the work queue to be empty.
    for _ in range(concurrency):
        worker()

    print("workers spwaned")

    yield q.join()

    print("done")


if __name__ == '__main__':
    io_loop = ioloop.IOLoop.current()
    io_loop.run_sync(main)

Поток ImpL прост (без мультиобработки) и использует следующий код

for i in range(concurrency):
  t = threading.Thread(target=worker, args=())
  t.setDaemon(True)
  t.start()

1 Ответ

0 голосов
/ 13 мая 2018

Существует несколько причин, по которым это может быть медленнее:

  1. Цель асинхронного программирования - не скорость , а масштабируемость .Асинхронная реализация должна работать лучше на высоких уровнях параллелизма (в частности, она будет использовать гораздо меньше памяти), но на низких уровнях параллелизма может не быть различий или потоки могут быть быстрее.

  2. HTTP-клиент Tornado по умолчанию написан на чистом Python и в нем отсутствуют некоторые функции, важные для производительности.В частности, он не может повторно использовать соединения.Если для вас важна производительность HTTP-запросов, используйте вместо этого клиент на основе libcurl:

    tornado.httpclient.AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')
    
  3. Иногда разрешение DNS блокируется даже в асинхронном HTTP-клиенте, который в противном случае можетограничить эффективный параллелизмЭто было верно для HTTP-клиента Tornado по умолчанию до Tornado 5.0.Для клиента на основе curl это зависит от того, как был построен libcurl.Вам нужна версия libcurl, созданная с помощью библиотеки c-ares.В прошлый раз, когда я посмотрел, это не было сделано по умолчанию в большинстве дистрибутивов Linux.

...