Извините, если я не ясно изложил свой вопрос, так как система сказала, что это плохой запрос, в котором отсутствует разъяснение проблемы.
Проблема (контекст), с которой я столкнулся, заключается в том, что у меня есть несколько синхронных API, завершение которых займет много времени, поскольку задействованы некоторые сетевые операции ввода-вывода. Итак, я думаю, как улучшить задержку (и производительность в том числе). Это большой вопрос, поэтому я разделю его на несколько подвопросов, и в этой ветке будет один такой подвопрос о том, может ли async/await улучшить задержку или нет. Я буду использовать приведенный ниже пример для своего сценария.
У меня есть API (скажем, FO1), который является синхронным, чтобы выполнить свою работу, FO1 вызовет метод (FO2), который вызовет другой метод (FO3), и общая цепочка вызовов методов равна FO1 -> FO2 -> FO3 ->... -> F9 -> F10
. F10 — асинхронный метод. Таким образом, чтобы вызвать асинхронный метод в контексте синхронизации, я должен принять решение о том, где остановить распространение async/await. Итак, мой вопрос: есть ли какие-либо различия (скажем, задержка или производительность) между цепочками ниже (методы, выделенные жирным шрифтом, являются асинхронными, а стандартные — синхронными):
Я думаю, что с точки зрения клиента (вызывающих абонентов FO1), задержки двух вышеперечисленных должны быть очень похожими, но не уверен, какой из них лучше?
Спасибо
Вы можете запустить базовый тест, используя BenchmarkDotNet
. Я сделал очень быстрый тест, 1 и 2 работают почти одинаково, но 2 выделяет примерно в 2,5 раза больше 1189 B
по сравнению с 478 B
.
Кроме того, если асинхронная операция часто будет на самом деле синхронной: есть способы избежать накладных расходов на конечный автомат, но это не автоматический - его нужно немного закодировать вручную.
Разницы практически никакой. Как было указано в комментариях, решение с большим количеством методов async
будет иметь больше мусора в памяти и немного более медленное выполнение, но оба эти фактора меркнут по сравнению со стоимостью ввода-вывода.
Если FO1 никогда не будет асинхронным, то я постараюсь сделать синхронным всю цепочку. Зачем что-то асинхронное, если оно просто будет заблокировано?
спасибо Стивен. Как поставщик API, у нас не всегда есть дополнительное решение, некоторые API действительно являются синхронными, но некоторые из них полагаются на некоторые внутренние асинхронные реализации.
Каждый раз, когда вы вызываете
await
, он должен создать реализациюIAsyncStateMachine
, и поэтому имеет накладные расходы (даже несмотря на некоторое кэширование), но, вероятно, он бледнеет по сравнению с вызовом ввода-вывода. Однако, если это горячий путь, вы можете просто пропустить (переслать результат задачи), а неawait
в каждом методе черезTask.FromResult
, просто не забудьте перехватить любые исключения метода и добавить их в возвращаемую задачу с помощьюTask.FromException