Есть ли разница в производительности относительно уровня глубины async/await в цепочке вызовов метода синхронизации (С#)?

Извините, если я не ясно изложил свой вопрос, так как система сказала, что это плохой запрос, в котором отсутствует разъяснение проблемы.

Проблема (контекст), с которой я столкнулся, заключается в том, что у меня есть несколько синхронных API, завершение которых займет много времени, поскольку задействованы некоторые сетевые операции ввода-вывода. Итак, я думаю, как улучшить задержку (и производительность в том числе). Это большой вопрос, поэтому я разделю его на несколько подвопросов, и в этой ветке будет один такой подвопрос о том, может ли async/await улучшить задержку или нет. Я буду использовать приведенный ниже пример для своего сценария.

У меня есть API (скажем, FO1), который является синхронным, чтобы выполнить свою работу, FO1 вызовет метод (FO2), который вызовет другой метод (FO3), и общая цепочка вызовов методов равна FO1 -> FO2 -> FO3 ->... -> F9 -> F10. F10 — асинхронный метод. Таким образом, чтобы вызвать асинхронный метод в контексте синхронизации, я должен принять решение о том, где остановить распространение async/await. Итак, мой вопрос: есть ли какие-либо различия (скажем, задержка или производительность) между цепочками ниже (методы, выделенные жирным шрифтом, являются асинхронными, а стандартные — синхронными):

  1. FO1 -> FO2 -> FO3 ->... -> F9 -> F10
  2. FO1 -> FO2 -> FO3 ->... -> F9 -> F10

Я думаю, что с точки зрения клиента (вызывающих абонентов FO1), задержки двух вышеперечисленных должны быть очень похожими, но не уверен, какой из них лучше?

Спасибо

Каждый раз, когда вы вызываете await, он должен создать реализацию IAsyncStateMachine, и поэтому имеет накладные расходы (даже несмотря на некоторое кэширование), но, вероятно, он бледнеет по сравнению с вызовом ввода-вывода. Однако, если это горячий путь, вы можете просто пропустить (переслать результат задачи), а не await в каждом методе через Task.FromResult, просто не забудьте перехватить любые исключения метода и добавить их в возвращаемую задачу с помощью Task.FromException

TheGeneral 11.12.2020 04:44

Вы можете запустить базовый тест, используя BenchmarkDotNet. Я сделал очень быстрый тест, 1 и 2 работают почти одинаково, но 2 выделяет примерно в 2,5 раза больше 1189 B по сравнению с 478 B.

JohanP 11.12.2020 05:22

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

Marc Gravell 11.12.2020 06:48
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
135
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Если FO1 никогда не будет асинхронным, то я постараюсь сделать синхронным всю цепочку. Зачем что-то асинхронное, если оно просто будет заблокировано?

спасибо Стивен. Как поставщик API, у нас не всегда есть дополнительное решение, некоторые API действительно являются синхронными, но некоторые из них полагаются на некоторые внутренние асинхронные реализации.

zjg.robin 14.12.2020 01:42

Другие вопросы по теме