Когда мне нужно использовать исполнителя для кода asyn c? Что произойдет, если я этого не сделаю (но должен)? - PullRequest
2 голосов
/ 08 мая 2020

Документы asyncio проясняют, что код asyncio не должен вызывать код блокировки напрямую, а также указывает способ запуска кода блокировки с помощью asyn c code:

Blocking Код (связанный с ЦП) не должен вызываться напрямую. Например, если функция выполняет расчет с интенсивным использованием ЦП в течение 1 секунды, все параллельные задачи asyncio и операции ввода-вывода будут отложены на 1 секунду.

Исполнитель может использоваться для запуска задачи в другом потоке или даже в другом процессе, чтобы избежать блокировки потока ОС событием l oop.

Однако это описание не очень конкретно c относительно того, в какой момент следует использовать исполнителя. Понятно, что «вычисление интенсивного использования ЦП в течение 1 секунды» будет проблемой, но будет ли проблема 0,1 с? или 0,01 с?

В документации также приводится пример

def cpu_bound():
    return sum(i * i for i in range(10 ** 7))

как что-то для запуска в экзекьюторе (который выполняется менее чем за секунду).

(Хотя они, вероятно, используют это как пример использования потоков и процессов, это все еще пример того, что я имею в виду - я бы запустил его в исполнителе, если бы это было range(10 ** 6), et c. )

В этом ответе указано, что

Большая часть стандартной библиотеки состоит из обычных, «блокирующих» функций и определений классов. Они выполняют свою работу быстро, поэтому, даже если они «блокируются», они возвращаются в разумные сроки.

...

Загрузка стандартных библиотечных функций и методов выполняется быстро, зачем вам это нужно? запустить str.splitlines() или urllib.parse.quote() в отдельном потоке, когда было бы намного быстрее просто выполнить код и покончить с ним?

Но что считается «разумным временем»? Когда я смогу «просто выполнить код и покончить с ним»?

Мои вопросы:

  1. Как вы определяете, что требуется исполнитель?
  2. Что на самом деле происходит, если ваш код слишком долго «блокируется»? Каковы признаки того, что это так?

1 Ответ

2 голосов
/ 08 мая 2020

Как вы определяете, что нужен исполнитель?

Вопрос не является уникальным для asyncio. Насколько мне известно, никто еще не придумал точного критерия.

Текущая практика такая же, как и с другими решениями, связанными с производительностью: определять, сочетая здравый смысл и профилирование. Здравый смысл подсказывает вам, что urllib.parse.quote() можно вызывать в потоке события l oop, но при синтаксическом анализе HTML документов произвольного размера с BeautifulSoup, вероятно, нет. Как показывает практика, сопрограммы могут включать в себя такой код, который вам удобно разместить в обратном вызове в классической c асинхронной c системе, такой как Twisted.

Что на самом деле происходит если ваш код слишком длинный "блокирует"? Каковы признаки того, что это так?

Вы заметите увеличенную задержку и уменьшение пропускной способности.

Ожидаемая задержка вашей программы, вероятно, будет фактором, определяющим, когда начинать с помощью исполнителей. Также обратите внимание, что передача чего-либо исполнителю имеет свои собственные немаловажные накладные расходы, поэтому вы не хотите делать это для всего, и это фактически замедлит работу, если вы сделаете это для очень быстрых вещей (например, кода это сводится к паре поисков dict).

...