Может ли асинхронное ожидание увеличить общее время выполнения функции - PullRequest
0 голосов
/ 05 ноября 2018

Мой вопрос относится к общему времени выполнения асинхронной функции по сравнению с синхронной функцией.

Мое понимание таково:

-Асинхронная функция вызывается

-Код выполняется до тех пор, пока не будет достигнут ожидаемый код

-При выполнении ожидаемого кода (например, чтение БД), поток выполнения освобождается для выполнения другой задачи

-Когда ожидаемый код завершен, назначен поток для завершения этого вызова

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

Мои рассуждения таковы:

  1. Асинхронность (отслеживание всего) накладных расходов

  2. Поскольку асинхронный код должен ждать, пока поток выполнит оставшийся код, он должен ждать, пока поток не станет доступным - поэтому, если все потоки заняты, ему придется ждать один?

Если это так, то я предполагаю, что это также означает, что если бы существовал ожидаемый метод, который не делал ввода-вывода, он все равно освободил бы исполняющий поток и дождался, когда следующий станет доступным для выполнения задачи.

UPDATE: Я знаю, что await / async не ускоряет время отклика, но позволяет серверу работать более эффективно.

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

ОБНОВЛЕНИЕ 2: Предположим, у меня есть хорошо спроектированная асинхронная система, но у меня есть один метод, который должен быть максимально быстрым и экономным - я не собираюсь ничего мешать времени выполнения этого одного вызова. Конечно, в этой ситуации, если я сделаю этот метод асинхронным и освободлю поток, вызов может потенциально ждать, пока поток завершит свое выполнение, если он асинхронный, тогда как, если он синхронизирован, поток всегда будет там ждать - при за счет производительности остальной части приложения?

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018
  1. Есть асинхронные издержки (отслеживание всего)

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

Основной момент, который я пытаюсь уточнить, заключается в том, что запрос может занять больше времени из-за того, что нет доступных потоков после завершения асинхронной задачи, например, если вызов db завершен, нужно ли когда-либо ждать больше времени для потока становится доступным?

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

Операция должна вернуться в очередь, но получает приоритет над операциями, которые еще не были начаты. Это очень похоже на, например, как работает почтовое отделение:

  • Вы в очереди
  • Вы попадаете на стойку регистрации, работник почты дает вам форму для заполнения (и, таким образом, ожидает вы заполняете эту форму)
  • Вы отходите в сторону и заполняете форму, пока работник почты может помогать другим, вместо того, чтобы бездельничать, пока она ждет вас.
  • Когда вы закончите со своей задачей, вы не откладываете клиента, которому в данный момент помогают, в сторону ... (это то, чего вы, похоже, хотите: получить немедленное внимание потока и не ждать окончания его работы) .
  • ... но вам разрешат прыгнуть в очередь перед людьми, которые еще не разговаривали с почтовым работником.

Примечание: по крайней мере, так моя культура (Западная Европа) справляется с этим. Ваш пробег может отличаться.

Итак, да, ваше предположение на самом деле верно; но я хочу подчеркнуть, что разница во времени здесь астрономически ничтожна по сравнению с выгодами от асинхронной работы.
Если вы хотите сжать определенную операцию для максимально быстрой производительности, вам придется предоставить ей собственный поток и не позволять ей участвовать в расписании «асинхронного пула». Но я настоятельно рекомендую против этого, поскольку выгода от этого будет чрезвычайно незначительной и никоим образом не перевесит сложность ее разработки.

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

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

Я не понимаю ваших рассуждений здесь.

Если вы предполагаете, что «поток ждет меня» в синхронном примере, это означает, что этот поток доступен и в данный момент не занят. Но для вашего асинхронного примера вы предполагаете, что все потоки заняты, и ни один не доступен.

Это совершенно разные ситуации. Если все потоки насыщены в асинхронном приложении, то все потоки (будь то один или несколько) в синхронном приложении также будут заняты.

Цель асинхронности совсем противоположна. Если поток в настоящее время занят, но находится в режиме ожидания, в синхронном приложении вы будете вынуждены ждать и не сможете использовать поток. Однако в асинхронном приложении ожидающий поток сможет начать обработку вашего запроса, так как он в настоящее время находится в режиме ожидания, поскольку ожидает другую задачу, которая еще не выполнена.

0 голосов
/ 05 ноября 2018

async-await больше об отзывчивости, чем производительность.

В клиентском пользовательском интерфейсе пользовательский интерфейс (обычно) управляется в одном потоке (потоке пользовательского интерфейса). Если вы заблокируете этот поток, пользовательский интерфейс будет заблокирован. async-await предоставляет механизм для запуска задачи вне потока пользовательского интерфейса и возобновления выполнения в потоке пользовательского интерфейса после завершения этой задачи. Эта задача может быть как интенсивным, так и интенсивным. Основная цель - выйти из потока пользовательского интерфейса.

На сервере (ASP.NET) пул потоков ограничен, поэтому освобождение потоков при выполнении ввода-вывода позволяет приложению обрабатывать больше запросов. С другой стороны, использование задач для работы с интенсивным использованием ЦП приведет к обмену одного потока пула потоков на другой дважды.

Все это дополнительная работа, которая, очевидно, использует больше ресурсов (такты процессора и память). Все дело в отзывчивости, а не в производительности.

...