Должен ли я вызвать мою асинхронную функцию в другом процессе / потоке? - PullRequest
1 голос
/ 07 июня 2019

Я делаю скриншот нескольких тысяч веб-страниц с помощью pyppeteer. Я случайно обнаружил, что выполнение одного и того же скрипта на 2 открытых терминалах удваивает вывод, который я получаю. Я проверил это, открыв до 6 терминалов и запустив скрипт, и мне удалось в 6 раз увеличить производительность.

Я рассматриваю возможность использования loop.run_in_executor для запуска сценария в нескольких процессах или потоках из основной программы.

Это правильный вызов, или я достигаю некоторого ограничения ввода / вывода в моем скрипте?

Вот как я думаю об этом. Я не знаю, правильно ли это делать.

import asyncio
import concurrent.futures

async def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

async def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

def wrap_blocking_io():
    return asyncio.run(blocking_io())

def wrap_cpu_bound():
    return asyncio.run(cpu_bound())

async def main():
    loop = asyncio.get_running_loop()
    # Options:
    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, wrap_blocking_io)
    print('default thread pool', result)
    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor(max_workers=6) as pool:
        result = await loop.run_in_executor(
            pool, wrap_blocking_io)
        print('custom thread pool', result)
    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor(max_workers=6) as pool:
        result = await loop.run_in_executor(
            pool, wrap_cpu_bound)
        print('custom process pool', result)

asyncio.run(main())

1 Ответ

1 голос
/ 07 июня 2019

Я проверил это, открыв до 6 терминалов и запустив скрипт, и мне удалось увеличить производительность до 6 раз.

Поскольку pyppeteer уже асинхронен, я полагаювы просто не запускаете несколько браузеров параллельно, и поэтому вы увеличиваете вывод при запуске нескольких процессов.

Для одновременного запуска некоторых сопрограмм («параллельно») вы обычно используете что-то вроде asyncio.gather.У вас есть код?Если ответ отрицательный, отметьте в этом примере - вот как вам следует запустить несколько заданий:

responses = await asyncio.gather(*tasks)

Если вы уже используете asyncio.gather, рассмотрите возможность предоставления Минимальное, Воспроизводимый пример , чтобы было легче понять, что происходит.

...